Page MenuHomeFreeBSD

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/CHANGES.md b/CHANGES.md
index 7cdd9d974536..0fb1eb1f6a71 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,19753 +1,19832 @@
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.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.
+
+ Ref: https://datatracker.ietf.org/doc/html/rfc2578#section-3.5
+
+ *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-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-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/Configure b/Configure
index 5ac4b5222e4f..4ddc275f787e 100755
--- a/Configure
+++ b/Configure
@@ -1,3594 +1,3594 @@
#! /usr/bin/env perl
# -*- mode: perl; -*-
# 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
## Configure -- OpenSSL source tree configuration script
use 5.10.0;
use strict;
use Config;
use FindBin;
use lib "$FindBin::Bin/util/perl";
use File::Basename;
use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs splitdir/;
use File::Path qw/mkpath/;
use OpenSSL::fallback "$FindBin::Bin/external/perl/MODULES.txt";
use OpenSSL::Glob;
use OpenSSL::Template;
use OpenSSL::config;
# see INSTALL.md for instructions.
my $orig_death_handler = $SIG{__DIE__};
$SIG{__DIE__} = \&death_handler;
my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] os/compiler[:flags]\n";
my $banner = <<"EOF";
**********************************************************************
*** ***
*** OpenSSL has been successfully configured ***
*** ***
*** If you encounter a problem while building, please open an ***
*** issue on GitHub <https://github.com/openssl/openssl/issues> ***
*** and include the output from the following command: ***
*** ***
*** perl configdata.pm --dump ***
*** ***
*** (If you are new to OpenSSL, you might want to consult the ***
*** 'Troubleshooting' section in the INSTALL.md file first) ***
*** ***
**********************************************************************
EOF
# Options:
#
# --config add the given configuration file, which will be read after
# any "Configurations*" files that are found in the same
# directory as this script.
# --prefix prefix for the OpenSSL installation, which includes the
# directories bin, lib, include, share/man, share/doc/openssl
# This becomes the value of INSTALLTOP in Makefile
# (Default: /usr/local)
# --openssldir OpenSSL data area, such as openssl.cnf, certificates and keys.
# If it's a relative directory, it will be added on the directory
# given with --prefix.
# This becomes the value of OPENSSLDIR in Makefile and in C.
# (Default: PREFIX/ssl)
# --banner=".." Output specified text instead of default completion banner
#
# -w Don't wait after showing a Configure warning
#
# --cross-compile-prefix Add specified prefix to binutils components.
#
# --api One of 0.9.8, 1.0.0, 1.0.1, 1.0.2, 1.1.0, 1.1.1, or 3.0
# Define the public APIs as they were for that version
# including patch releases. If 'no-deprecated' is also
# given, do not compile support for interfaces deprecated
# up to and including the specified OpenSSL version.
#
# no-hw-xxx do not compile support for specific crypto hardware.
# Generic OpenSSL-style methods relating to this support
# are always compiled but return NULL if the hardware
# support isn't compiled.
# no-hw do not compile support for any crypto hardware.
# [no-]threads [don't] try to create a library that is suitable for
# multithreaded applications (default is "threads" if we
# know how to do it)
# [no-]shared [don't] try to create shared libraries when supported.
# [no-]pic [don't] try to build position independent code when supported.
# If disabled, it also disables shared and dynamic-engine.
# no-asm do not use assembler
# no-egd do not compile support for the entropy-gathering daemon APIs
# [no-]zlib [don't] compile support for zlib compression.
# zlib-dynamic Like "zlib", but the zlib library is expected to be a shared
# library and will be loaded in run-time by the OpenSSL library.
# sctp include SCTP support
# no-uplink Don't build support for UPLINK interface.
# enable-weak-ssl-ciphers
# Enable weak ciphers that are disabled by default.
# 386 generate 80386 code in assembly modules
# no-sse2 disables IA-32 SSE2 code in assembly modules, the above
# mentioned '386' option implies this one
# no-<cipher> build without specified algorithm (dsa, idea, rc5, ...)
# -<xxx> +<xxx> All options which are unknown to the 'Configure' script are
# /<xxx> passed through to the compiler. Unix-style options beginning
# with a '-' or '+' are recognized, as well as Windows-style
# options beginning with a '/'. If the option contains arguments
# separated by spaces, then the URL-style notation %20 can be
# used for the space character in order to avoid having to quote
# the option. For example, -opt%20arg gets expanded to -opt arg.
# In fact, any ASCII character can be encoded as %xx using its
# hexadecimal encoding.
# -static while -static is also a pass-through compiler option (and
# as such is limited to environments where it's actually
# meaningful), it triggers a number configuration options,
# namely no-pic, no-shared and no-threads. It is
# argued that the only reason to produce statically linked
# binaries (and in context it means executables linked with
# -static flag, and not just executables linked with static
# libcrypto.a) is to eliminate dependency on specific run-time,
# a.k.a. libc version. The mentioned config options are meant
# to achieve just that. Unfortunately on Linux it's impossible
# to eliminate the dependency completely for openssl executable
# because of getaddrinfo and gethostbyname calls, which can
# invoke dynamically loadable library facility anyway to meet
# the lookup requests. For this reason on Linux statically
# linked openssl executable has rather debugging value than
# production quality.
#
# BN_LLONG use the type 'long long' in crypto/bn/bn.h
# RC4_CHAR use 'char' instead of 'int' for RC4_INT in crypto/rc4/rc4.h
# Following are set automatically by this script
#
# MD5_ASM use some extra md5 assembler,
# SHA1_ASM use some extra sha1 assembler, must define L_ENDIAN for x86
# RMD160_ASM use some extra ripemd160 assembler,
# SHA256_ASM sha256_block is implemented in assembler
# SHA512_ASM sha512_block is implemented in assembler
# AES_ASM AES_[en|de]crypt is implemented in assembler
# Minimum warning options... any contributions to OpenSSL should at least
# get past these. Note that we only use these with C compilers, not with
# C++ compilers.
# -DPEDANTIC complements -pedantic and is meant to mask code that
# is not strictly standard-compliant and/or implementation-specific,
# e.g. inline assembly, disregards to alignment requirements, such
# that -pedantic would complain about. Incidentally -DPEDANTIC has
# to be used even in sanitized builds, because sanitizer too is
# supposed to and does take notice of non-standard behaviour. Then
# -pedantic with pre-C9x compiler would also complain about 'long
# long' not being supported. As 64-bit algorithms are common now,
# it grew impossible to resolve this without sizeable additional
# code, so we just tell compiler to be pedantic about everything
# but 'long long' type.
my @gcc_devteam_warn = qw(
-DPEDANTIC -pedantic -Wno-long-long -DUNUSEDRESULT_DEBUG
-Wall
-Wmissing-declarations
-Wextra
-Wno-unused-parameter
-Wno-missing-field-initializers
-Wswitch
-Wsign-compare
-Wshadow
-Wformat
-Wtype-limits
-Wundef
-Werror
-Wmissing-prototypes
-Wstrict-prototypes
);
# These are used in addition to $gcc_devteam_warn when the compiler is clang.
# TODO(openssl-team): fix problems and investigate if (at least) the
# following warnings can also be enabled:
# -Wcast-align
# -Wunreachable-code -- no, too ugly/compiler-specific
# -Wlanguage-extension-token -- no, we use asm()
# -Wunused-macros -- no, too tricky for BN and _XOPEN_SOURCE etc
# -Wextended-offsetof -- no, needed in CMS ASN1 code
my @clang_devteam_warn = qw(
-Wno-unknown-warning-option
-Wswitch-default
-Wno-parentheses-equality
-Wno-language-extension-token
-Wno-extended-offsetof
-Wconditional-uninitialized
-Wincompatible-pointer-types-discards-qualifiers
-Wmissing-variable-declarations
);
my @cl_devteam_warn = qw(
/WX
);
my $strict_warnings = 0;
# As for $BSDthreads. Idea is to maintain "collective" set of flags,
# which would cover all BSD flavors. -pthread applies to them all,
# but is treated differently. OpenBSD expands is as -D_POSIX_THREAD
# -lc_r, which is sufficient. FreeBSD 4.x expands it as -lc_r,
# which has to be accompanied by explicit -D_THREAD_SAFE and
# sometimes -D_REENTRANT. FreeBSD 5.x expands it as -lc_r, which
# seems to be sufficient?
our $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT";
#
# API compatibility name to version number mapping.
#
my $apitable = {
# This table expresses when API additions or changes can occur.
# The numbering used changes from 3.0 and on because we updated
# (solidified) our version numbering scheme at that point.
# From 3.0 and on, we internalise the given version number in decimal
# as MAJOR * 10000 + MINOR * 100 + 0
"3.0.0" => 30000,
"3.0" => 30000,
# Note that before 3.0, we didn't have the same version number scheme.
# Still, the numbering we use here covers what we need.
"1.1.1" => 10101,
"1.1.0" => 10100,
"1.0.2" => 10002,
"1.0.1" => 10001,
"1.0.0" => 10000,
"0.9.8" => 908,
};
# For OpenSSL::config::get_platform
my %guess_opts = ();
my $dryrun = 0;
our %table = ();
our %config = ();
our %withargs = ();
our $now_printing; # set to current entry's name in print_table_entry
# (todo: right thing would be to encapsulate name
# into %target [class] and make print_table_entry
# a method)
# Forward declarations ###############################################
# read_config(filename)
#
# Reads a configuration file and populates %table with the contents
# (which the configuration file places in %targets).
sub read_config;
# resolve_config(target)
#
# Resolves all the late evaluations, inheritances and so on for the
# chosen target and any target it inherits from.
sub resolve_config;
# Information collection #############################################
# Unified build supports separate build dir
my $srcdir = catdir(absolutedir(dirname($0))); # catdir ensures local syntax
my $blddir = catdir(absolutedir(".")); # catdir ensures local syntax
# File::Spec::Unix doesn't detect case insensitivity, so we make sure to
# check if the source and build directory are really the same, and make
# them so. This avoids all kinds of confusion later on.
# We must check @File::Spec::ISA rather than using File::Spec->isa() to
# know if File::Spec ended up loading File::Spec::Unix.
$srcdir = $blddir
if (grep(/::Unix$/, @File::Spec::ISA)
&& samedir($srcdir, $blddir));
my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl"));
my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR';
$config{sourcedir} = abs2rel($srcdir, $blddir);
$config{builddir} = abs2rel($blddir, $blddir);
# echo -n 'holy hand grenade of antioch' | openssl sha256
$config{FIPSKEY} =
'f4556650ac31d35461610bac4ed81b1a181b2d8a43ea2854cbae22ca74560813';
# Collect reconfiguration information if needed
my @argvcopy=@ARGV;
if (grep /^reconf(igure)?$/, @argvcopy) {
die "reconfiguring with other arguments present isn't supported"
if scalar @argvcopy > 1;
if (-f "./configdata.pm") {
my $file = "./configdata.pm";
unless (my $return = do $file) {
die "couldn't parse $file: $@" if $@;
die "couldn't do $file: $!" unless defined $return;
die "couldn't run $file" unless $return;
}
@argvcopy = defined($configdata::config{perlargv}) ?
@{$configdata::config{perlargv}} : ();
die "Incorrect data to reconfigure, please do a normal configuration\n"
if (grep(/^reconf/,@argvcopy));
$config{perlenv} = $configdata::config{perlenv} // {};
} else {
die "Insufficient data to reconfigure, please do a normal configuration\n";
}
}
$config{perlargv} = [ @argvcopy ];
# Historical: if known directories in crypto/ have been removed, it means
# that those sub-systems are disabled.
# (the other option would be to removed them from the SUBDIRS statement in
# crypto/build.info)
# We reverse the input list for cosmetic purely reasons, to compensate that
# 'unshift' adds at the front of the list (i.e. in reverse input order).
foreach ( reverse sort( 'aes', 'aria', 'bf', 'camellia', 'cast', 'des', 'dh',
'dsa', 'ec', 'hmac', 'idea', 'md2', 'md5', 'mdc2',
'rc2', 'rc4', 'rc5', 'ripemd', 'seed', 'sha',
'sm2', 'sm3', 'sm4') ) {
unshift @argvcopy, "no-$_" if ! -d catdir($srcdir, 'crypto', $_);
}
# Collect version numbers
my %version = ();
collect_information(
collect_from_file(catfile($srcdir,'VERSION.dat')),
qr/\s*(\w+)\s*=\s*(.*?)\s*$/ =>
sub {
# Only define it if there is a value at all
if ($2 ne '') {
my $k = $1;
my $v = $2;
# Some values are quoted. Trim the quotes
$v = $1 if $v =~ /^"(.*)"$/;
$version{uc $k} = $v;
}
},
"OTHERWISE" =>
sub { die "Something wrong with this line:\n$_\nin $srcdir/VERSION.dat" },
);
$config{major} = $version{MAJOR} // 'unknown';
$config{minor} = $version{MINOR} // 'unknown';
$config{patch} = $version{PATCH} // 'unknown';
$config{prerelease} =
defined $version{PRE_RELEASE_TAG} ? "-$version{PRE_RELEASE_TAG}" : '';
$config{build_metadata} =
defined $version{BUILD_METADATA} ? "+$version{BUILD_METADATA}" : '';
$config{shlib_version} = $version{SHLIB_VERSION} // 'unknown';
$config{release_date} = $version{RELEASE_DATE} // 'xx XXX xxxx';
$config{version} = "$config{major}.$config{minor}.$config{patch}";
$config{full_version} = "$config{version}$config{prerelease}$config{build_metadata}";
die "erroneous version information in VERSION.dat: ",
"$config{version}, $config{shlib_version}\n"
unless (defined $version{MAJOR}
&& defined $version{MINOR}
&& defined $version{PATCH}
&& defined $version{SHLIB_VERSION});
# Collect target configurations
my $pattern = catfile(dirname($0), "Configurations", "*.conf");
foreach (sort glob($pattern)) {
&read_config($_);
}
if (defined env($local_config_envname)) {
if ($^O eq 'VMS') {
# VMS environment variables are logical names,
# which can be used as is
$pattern = $local_config_envname . ':' . '*.conf';
} else {
$pattern = catfile(env($local_config_envname), '*.conf');
}
foreach (sort glob($pattern)) {
&read_config($_);
}
}
# Save away perl command information
$config{perl_cmd} = $^X;
$config{perl_version} = $Config{version};
$config{perl_archname} = $Config{archname};
$config{prefix}="";
$config{openssldir}="";
$config{processor}="";
$config{libdir}="";
my $auto_threads=1; # enable threads automatically? true by default
my $default_ranlib;
# Known TLS and DTLS protocols
my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3);
my @dtls = qw(dtls1 dtls1_2);
# Explicitly known options that are possible to disable. They can
# be regexps, and will be used like this: /^no-${option}$/
# For developers: keep it sorted alphabetically
my @disablables = (
"acvp-tests",
"afalgeng",
"aria",
"asan",
"asm",
"async",
"autoalginit",
"autoerrinit",
"autoload-config",
"bf",
"blake2",
"buildtest-c++",
"bulk",
"cached-fetch",
"camellia",
"capieng",
"cast",
"chacha",
"cmac",
"cmp",
"cms",
"comp",
"crypto-mdebug",
"ct",
"deprecated",
"des",
"devcryptoeng",
"dgram",
"dh",
"dsa",
"dso",
"dtls",
"dynamic-engine",
"ec",
"ec2m",
"ec_nistp_64_gcc_128",
"ecdh",
"ecdsa",
"egd",
"engine",
"err",
"external-tests",
"filenames",
"fips",
"fips-securitychecks",
"fuzz-afl",
"fuzz-libfuzzer",
"gost",
"idea",
"ktls",
"legacy",
"loadereng",
"makedepend",
"md2",
"md4",
"mdc2",
"module",
"msan",
"multiblock",
"nextprotoneg",
"ocb",
"ocsp",
"padlockeng",
"pic",
"pinshared",
"poly1305",
"posix-io",
"psk",
"rc2",
"rc4",
"rc5",
"rdrand",
"rfc3779",
"rmd160",
"scrypt",
"sctp",
"secure-memory",
"seed",
"shared",
"siphash",
"siv",
"sm2",
"sm3",
"sm4",
"sock",
"srp",
"srtp",
"sse2",
"ssl",
"ssl-trace",
"static-engine",
"stdio",
"tests",
"threads",
"tls",
"trace",
"ts",
"ubsan",
"ui-console",
"unit-test",
"uplink",
"weak-ssl-ciphers",
"whirlpool",
"zlib",
"zlib-dynamic",
);
foreach my $proto ((@tls, @dtls))
{
push(@disablables, $proto);
push(@disablables, "$proto-method") unless $proto eq "tls1_3";
}
# Internal disablables, for aliasing purposes. They serve no special
# purpose here, but allow scripts to get to know them through configdata.pm,
# where these are merged with @disablables.
# The actual aliasing mechanism is done via %disable_cascades
my @disablables_int = qw(
crmf
);
my %deprecated_disablables = (
"ssl2" => undef,
"buf-freelists" => undef,
"crypto-mdebug-backtrace" => undef,
"hw" => "hw", # causes cascade, but no macro
"hw-padlock" => "padlockeng",
"ripemd" => "rmd160",
"ui" => "ui-console",
"heartbeats" => undef,
);
# All of the following are disabled by default:
our %disabled = ( # "what" => "comment"
"fips" => "default",
"asan" => "default",
"buildtest-c++" => "default",
"crypto-mdebug" => "default",
"crypto-mdebug-backtrace" => "default",
"devcryptoeng" => "default",
"ec_nistp_64_gcc_128" => "default",
"egd" => "default",
"external-tests" => "default",
"fuzz-afl" => "default",
"fuzz-libfuzzer" => "default",
"ktls" => "default",
"md2" => "default",
"msan" => "default",
"rc5" => "default",
"sctp" => "default",
"ssl3" => "default",
"ssl3-method" => "default",
"trace" => "default",
"ubsan" => "default",
"unit-test" => "default",
"weak-ssl-ciphers" => "default",
"zlib" => "default",
"zlib-dynamic" => "default",
);
# Note: => pair form used for aesthetics, not to truly make a hash table
my @disable_cascades = (
# "what" => [ "cascade", ... ]
"bulk" => [ "shared", "dso",
"aria", "async", "autoload-config",
"blake2", "bf", "camellia", "cast", "chacha",
"cmac", "cms", "cmp", "comp", "ct",
"des", "dgram", "dh", "dsa",
"ec", "engine",
"filenames",
"idea", "ktls",
"md4", "multiblock", "nextprotoneg",
"ocsp", "ocb", "poly1305", "psk",
"rc2", "rc4", "rmd160",
"seed", "siphash", "siv",
"sm3", "sm4", "srp",
"srtp", "ssl3-method", "ssl-trace",
"ts", "ui-console", "whirlpool",
"fips-securitychecks" ],
sub { $config{processor} eq "386" }
=> [ "sse2" ],
"ssl" => [ "ssl3" ],
"ssl3-method" => [ "ssl3" ],
"zlib" => [ "zlib-dynamic" ],
"des" => [ "mdc2" ],
"ec" => [ "ec2m", "ecdsa", "ecdh", "sm2", "gost" ],
"dgram" => [ "dtls", "sctp" ],
"sock" => [ "dgram" ],
"dtls" => [ @dtls ],
sub { 0 == scalar grep { !$disabled{$_} } @dtls }
=> [ "dtls" ],
"tls" => [ @tls ],
sub { 0 == scalar grep { !$disabled{$_} } @tls }
=> [ "tls" ],
"crypto-mdebug" => [ "crypto-mdebug-backtrace" ],
# If no modules, then no dynamic engines either
"module" => [ "dynamic-engine" ],
# Without shared libraries, dynamic engines aren't possible.
# This is due to them having to link with libcrypto and register features
# using the ENGINE functionality, and since that relies on global tables,
# those *have* to be exacty the same as the ones accessed from the app,
# which cannot be guaranteed if shared libraries aren't present.
# (note that even with shared libraries, both the app and dynamic engines
# must be linked with the same library)
"shared" => [ "dynamic-engine", "uplink" ],
"dso" => [ "dynamic-engine", "module" ],
# Other modules don't necessarily have to link with libcrypto, so shared
# libraries do not have to be a condition to produce those.
# Without position independent code, there can be no shared libraries
# or modules.
"pic" => [ "shared", "module" ],
"module" => [ "fips", "dso" ],
"engine" => [ "dynamic-engine", grep(/eng$/, @disablables) ],
"dynamic-engine" => [ "loadereng" ],
"hw" => [ "padlockeng" ],
# no-autoalginit is only useful when building non-shared
"autoalginit" => [ "shared", "apps", "fips" ],
"stdio" => [ "apps", "capieng", "egd" ],
"apps" => [ "tests" ],
"tests" => [ "external-tests" ],
"comp" => [ "zlib" ],
"sm3" => [ "sm2" ],
sub { !$disabled{"unit-test"} } => [ "heartbeats" ],
sub { !$disabled{"msan"} } => [ "asm" ],
"cmac" => [ "siv" ],
"legacy" => [ "md2" ],
"cmp" => [ "crmf" ],
"fips" => [ "fips-securitychecks", "acvp-tests" ],
"deprecated-3.0" => [ "engine", "srp" ]
);
# Avoid protocol support holes. Also disable all versions below N, if version
# N is disabled while N+1 is enabled.
#
my @list = (reverse @tls);
while ((my $first, my $second) = (shift @list, shift @list)) {
last unless @list;
push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
=> [ @list ] );
unshift @list, $second;
}
my @list = (reverse @dtls);
while ((my $first, my $second) = (shift @list, shift @list)) {
last unless @list;
push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
=> [ @list ] );
unshift @list, $second;
}
# Explicit "no-..." options will be collected in %disabled along with the defaults.
# To remove something from %disabled, use "enable-foo".
# For symmetry, "disable-foo" is a synonym for "no-foo".
# For the "make variables" CPPINCLUDES and CPPDEFINES, we support lists with
# platform specific list separators. Users from those platforms should
# recognise those separators from how you set up the PATH to find executables.
# The default is the Unix like separator, :, but as an exception, we also
# support the space as separator.
my $list_separator_re =
{ VMS => qr/(?<!\^),/,
MSWin32 => qr/(?<!\\);/ } -> {$^O} // qr/(?<!\\)[:\s]/;
# All the "make variables" we support
# Some get pre-populated for the sake of backward compatibility
# (we supported those before the change to "make variable" support.
my %user = (
AR => env('AR'),
ARFLAGS => [],
AS => undef,
ASFLAGS => [],
CC => env('CC'),
CFLAGS => [ env('CFLAGS') || () ],
CXX => env('CXX'),
CXXFLAGS => [ env('CXXFLAGS') || () ],
CPP => undef,
CPPFLAGS => [ env('CPPFLAGS') || () ], # -D, -I, -Wp,
CPPDEFINES => [], # Alternative for -D
CPPINCLUDES => [], # Alternative for -I
CROSS_COMPILE => env('CROSS_COMPILE'),
HASHBANGPERL=> env('HASHBANGPERL') || env('PERL'),
LD => undef,
LDFLAGS => [ env('LDFLAGS') || () ], # -L, -Wl,
LDLIBS => [ env('LDLIBS') || () ], # -l
MT => undef,
MTFLAGS => [],
PERL => env('PERL') || ($^O ne "VMS" ? $^X : "perl"),
RANLIB => env('RANLIB'),
RC => env('RC') || env('WINDRES'),
RCFLAGS => [ env('RCFLAGS') || () ],
RM => undef,
);
# Info about what "make variables" may be prefixed with the cross compiler
# prefix. This should NEVER mention any such variable with a list for value.
my @user_crossable = qw ( AR AS CC CXX CPP LD MT RANLIB RC );
# The same but for flags given as Configure options. These are *additional*
# input, as opposed to the VAR=string option that override the corresponding
# config target attributes
my %useradd = (
CPPDEFINES => [],
CPPINCLUDES => [],
CPPFLAGS => [],
CFLAGS => [],
CXXFLAGS => [],
LDFLAGS => [],
LDLIBS => [],
RCFLAGS => [],
);
my %user_synonyms = (
HASHBANGPERL=> 'PERL',
RC => 'WINDRES',
);
# Some target attributes have been renamed, this is the translation table
my %target_attr_translate =(
ar => 'AR',
as => 'AS',
cc => 'CC',
cxx => 'CXX',
cpp => 'CPP',
hashbangperl => 'HASHBANGPERL',
ld => 'LD',
mt => 'MT',
ranlib => 'RANLIB',
rc => 'RC',
rm => 'RM',
);
# Initialisers coming from 'config' scripts
$config{defines} = [ split(/$list_separator_re/, env('__CNF_CPPDEFINES')) ];
$config{includes} = [ split(/$list_separator_re/, env('__CNF_CPPINCLUDES')) ];
$config{cppflags} = [ env('__CNF_CPPFLAGS') || () ];
$config{cflags} = [ env('__CNF_CFLAGS') || () ];
$config{cxxflags} = [ env('__CNF_CXXFLAGS') || () ];
$config{lflags} = [ env('__CNF_LDFLAGS') || () ];
$config{ex_libs} = [ env('__CNF_LDLIBS') || () ];
$config{openssl_api_defines}=[];
$config{openssl_sys_defines}=[];
$config{openssl_feature_defines}=[];
$config{options}="";
$config{build_type} = "release";
my $target="";
my %cmdvars = (); # Stores FOO='blah' type arguments
my %unsupported_options = ();
my %deprecated_options = ();
# If you change this, update apps/version.c
my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom);
my @seed_sources = ();
while (@argvcopy)
{
$_ = shift @argvcopy;
# Support env variable assignments among the options
if (m|^(\w+)=(.+)?$|)
{
$cmdvars{$1} = $2;
# Every time a variable is given as a configuration argument,
# it acts as a reset if the variable.
if (exists $user{$1})
{
$user{$1} = ref $user{$1} eq "ARRAY" ? [] : undef;
}
#if (exists $useradd{$1})
# {
# $useradd{$1} = [];
# }
next;
}
# VMS is a case insensitive environment, and depending on settings
# out of our control, we may receive options uppercased. Let's
# downcase at least the part before any equal sign.
if ($^O eq "VMS")
{
s/^([^=]*)/lc($1)/e;
}
# some people just can't read the instructions, clang people have to...
s/^-no-(?!integrated-as)/no-/;
# rewrite some options in "enable-..." form
s /^-?-?shared$/enable-shared/;
s /^sctp$/enable-sctp/;
s /^threads$/enable-threads/;
s /^zlib$/enable-zlib/;
s /^zlib-dynamic$/enable-zlib-dynamic/;
s /^fips$/enable-fips/;
if (/^(no|disable|enable)-(.+)$/)
{
my $word = $2;
if ($word !~ m|hw(?:-.+)| # special treatment for hw regexp opt
&& !exists $deprecated_disablables{$word}
&& !grep { $word eq $_ } @disablables)
{
$unsupported_options{$_} = 1;
next;
}
}
if (/^no-(.+)$/ || /^disable-(.+)$/)
{
foreach my $proto ((@tls, @dtls))
{
if ($1 eq "$proto-method")
{
$disabled{"$proto"} = "option($proto-method)";
last;
}
}
if ($1 eq "dtls")
{
foreach my $proto (@dtls)
{
$disabled{$proto} = "option(dtls)";
}
$disabled{"dtls"} = "option(dtls)";
}
elsif ($1 eq "ssl")
{
# Last one of its kind
$disabled{"ssl3"} = "option(ssl)";
}
elsif ($1 eq "tls")
{
# XXX: Tests will fail if all SSL/TLS
# protocols are disabled.
foreach my $proto (@tls)
{
$disabled{$proto} = "option(tls)";
}
}
elsif ($1 eq "static-engine")
{
delete $disabled{"dynamic-engine"};
}
elsif ($1 eq "dynamic-engine")
{
$disabled{"dynamic-engine"} = "option";
}
elsif (exists $deprecated_disablables{$1})
{
$deprecated_options{$_} = 1;
if (defined $deprecated_disablables{$1})
{
$disabled{$deprecated_disablables{$1}} = "option";
}
}
elsif ($1 =~ m|hw(?:-.+)|) # deprecate hw options in regexp form
{
$deprecated_options{$_} = 1;
}
else
{
$disabled{$1} = "option";
}
# No longer an automatic choice
$auto_threads = 0 if ($1 eq "threads");
}
elsif (/^enable-(.+)$/)
{
if ($1 eq "static-engine")
{
$disabled{"dynamic-engine"} = "option";
}
elsif ($1 eq "dynamic-engine")
{
delete $disabled{"dynamic-engine"};
}
elsif ($1 eq "zlib-dynamic")
{
delete $disabled{"zlib"};
}
my $algo = $1;
delete $disabled{$algo};
# No longer an automatic choice
$auto_threads = 0 if ($1 eq "threads");
}
elsif (/^-d$/) # From older 'config'
{
$config{build_type} = "debug";
}
elsif (/^-v$/) # From older 'config'
{
$guess_opts{verbose} = 1;
}
elsif (/^-w$/)
{
$guess_opts{nowait} = 1;
}
elsif (/^-t$/) # From older 'config'
{
$dryrun = 1;
}
elsif (/^--strict-warnings$/)
{
# Pretend that our strict flags is a C flag, and replace it
# with the proper flags later on
push @{$useradd{CFLAGS}}, '--ossl-strict-warnings';
$strict_warnings=1;
}
elsif (/^--debug$/)
{
$config{build_type} = "debug";
}
elsif (/^--release$/)
{
$config{build_type} = "release";
}
elsif (/^386$/)
{ $config{processor}=386; }
elsif (/^rsaref$/)
{
# No RSAref support any more since it's not needed.
# The check for the option is there so scripts aren't
# broken
}
elsif (m|^[-+/]|)
{
if (/^--prefix=(.*)$/)
{
$config{prefix}=$1;
die "Directory given with --prefix MUST be absolute\n"
unless file_name_is_absolute($config{prefix});
}
elsif (/^--api=(.*)$/)
{
my $api = $1;
die "Unknown API compatibility level $api"
unless defined $apitable->{$api};
$config{api}=$apitable->{$api};
}
elsif (/^--libdir=(.*)$/)
{
$config{libdir}=$1;
}
elsif (/^--openssldir=(.*)$/)
{
$config{openssldir}=$1;
}
elsif (/^--with-zlib-lib=(.*)$/)
{
$withargs{zlib_lib}=$1;
}
elsif (/^--with-zlib-include=(.*)$/)
{
$withargs{zlib_include}=$1;
}
elsif (/^--with-fuzzer-lib=(.*)$/)
{
$withargs{fuzzer_lib}=$1;
}
elsif (/^--with-fuzzer-include=(.*)$/)
{
$withargs{fuzzer_include}=$1;
}
elsif (/^--with-rand-seed=(.*)$/)
{
foreach my $x (split(m|,|, $1))
{
die "Unknown --with-rand-seed choice $x\n"
if ! grep { $x eq $_ } @known_seed_sources;
push @seed_sources, $x;
}
}
elsif (/^--fips-key=(.*)$/)
{
$user{FIPSKEY}=lc($1);
die "Non-hex character in FIPS key\n"
if $user{FIPSKEY} =~ /[^a-f0-9]/;
die "FIPS key must have even number of characters\n"
if length $1 & 1;
die "FIPS key too long (64 bytes max)\n"
if length $1 > 64;
}
elsif (/^--banner=(.*)$/)
{
$banner = $1 . "\n";
}
elsif (/^--cross-compile-prefix=(.*)$/)
{
$user{CROSS_COMPILE}=$1;
}
elsif (/^--config=(.*)$/)
{
read_config $1;
}
elsif (/^-l(.*)$/)
{
push @{$useradd{LDLIBS}}, $_;
}
elsif (/^-framework$/)
{
push @{$useradd{LDLIBS}}, $_, shift(@argvcopy);
}
elsif (/^-L(.*)$/ or /^-Wl,/)
{
push @{$useradd{LDFLAGS}}, $_;
}
elsif (/^-rpath$/ or /^-R$/)
# -rpath is the OSF1 rpath flag
# -R is the old Solaris rpath flag
{
my $rpath = shift(@argvcopy) || "";
$rpath .= " " if $rpath ne "";
push @{$useradd{LDFLAGS}}, $_, $rpath;
}
elsif (/^-static$/)
{
push @{$useradd{LDFLAGS}}, $_;
}
elsif (m|^[-/]D(.*)$|)
{
push @{$useradd{CPPDEFINES}}, $1;
}
elsif (m|^[-/]I(.*)$|)
{
push @{$useradd{CPPINCLUDES}}, $1;
}
elsif (/^-Wp,$/)
{
push @{$useradd{CPPFLAGS}}, $1;
}
else # common if (/^[-+]/), just pass down...
{
# Treat %xx as an ASCII code (e.g. replace %20 by a space character).
# This provides a simple way to pass options with arguments separated
# by spaces without quoting (e.g. -opt%20arg translates to -opt arg).
$_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
push @{$useradd{CFLAGS}}, $_;
push @{$useradd{CXXFLAGS}}, $_;
}
}
elsif (m|^/|)
{
# Treat %xx as an ASCII code (e.g. replace %20 by a space character).
# This provides a simple way to pass options with arguments separated
# by spaces without quoting (e.g. /opt%20arg translates to /opt arg).
$_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
push @{$useradd{CFLAGS}}, $_;
push @{$useradd{CXXFLAGS}}, $_;
}
else
{
die "target already defined - $target (offending arg: $_)\n" if ($target ne "");
$target=$_;
}
unless ($_ eq $target || /^no-/ || /^disable-/)
{
# "no-..." follows later after implied deactivations
# have been derived. (Don't take this too seriously,
# we really only write OPTIONS to the Makefile out of
# nostalgia.)
if ($config{options} eq "")
{ $config{options} = $_; }
else
{ $config{options} .= " ".$_; }
}
}
if (keys %deprecated_options)
{
warn "***** Deprecated options: ",
join(", ", keys %deprecated_options), "\n";
}
if (keys %unsupported_options)
{
die "***** Unsupported options: ",
join(", ", keys %unsupported_options), "\n";
}
# If any %useradd entry has been set, we must check that the "make
# variables" haven't been set. We start by checking of any %useradd entry
# is set.
if (grep { scalar @$_ > 0 } values %useradd) {
# Hash of env / make variables names. The possible values are:
# 1 - "make vars"
# 2 - %useradd entry set
# 3 - both set
my %detected_vars =
map { my $v = 0;
$v += 1 if $cmdvars{$_};
$v += 2 if @{$useradd{$_}};
$_ => $v }
keys %useradd;
# If any of the corresponding "make variables" is set, we error
if (grep { $_ & 1 } values %detected_vars) {
my $names = join(', ', grep { $detected_vars{$_} > 0 }
sort keys %detected_vars);
die <<"_____";
***** Mixing make variables and additional compiler/linker flags as
***** configure command line option is not permitted.
***** Affected make variables: $names
_____
}
}
# Check through all supported command line variables to see if any of them
# were set, and canonicalise the values we got. If no compiler or linker
# flag or anything else that affects %useradd was set, we also check the
# environment for values.
my $anyuseradd =
grep { defined $_ && (ref $_ ne 'ARRAY' || @$_) } values %useradd;
foreach (keys %user) {
my $value = $cmdvars{$_};
$value //= env($_) unless $anyuseradd;
$value //=
defined $user_synonyms{$_} ? $cmdvars{$user_synonyms{$_}} : undef;
$value //= defined $user_synonyms{$_} ? env($user_synonyms{$_}) : undef
unless $anyuseradd;
if (defined $value) {
if (ref $user{$_} eq 'ARRAY') {
if ($_ eq 'CPPDEFINES' || $_ eq 'CPPINCLUDES') {
$user{$_} = [ split /$list_separator_re/, $value ];
} else {
$user{$_} = [ $value ];
}
} elsif (!defined $user{$_}) {
$user{$_} = $value;
}
}
}
if (grep { /-rpath\b/ } ($user{LDFLAGS} ? @{$user{LDFLAGS}} : ())
&& !$disabled{shared}
&& !($disabled{asan} && $disabled{msan} && $disabled{ubsan})) {
die "***** Cannot simultaneously use -rpath, shared libraries, and\n",
"***** any of asan, msan or ubsan\n";
}
# If no target was given, try guessing.
unless ($target) {
my %system_config = OpenSSL::config::get_platform(%guess_opts, %user);
# The $system_config{disable} is used to populate %disabled with
# entries that aren't already there.
foreach ( @{$system_config{disable} // []} ) {
$disabled{$_} = 'system' unless defined $disabled{$_};
}
delete $system_config{disable};
# Override config entries with stuff from the guesser.
# It's assumed that this really is nothing new.
%config = ( %config, %system_config );
$target = $system_config{target};
}
sub disable {
my $disable_type = shift;
for (@_) {
$disabled{$_} = $disable_type;
}
my @tocheckfor = (@_ ? @_ : keys %disabled);
while (@tocheckfor) {
my %new_tocheckfor = ();
my @cascade_copy = (@disable_cascades);
while (@cascade_copy) {
my ($test, $descendents) =
(shift @cascade_copy, shift @cascade_copy);
if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) {
foreach (grep { !defined($disabled{$_}) } @$descendents) {
$new_tocheckfor{$_} = 1; $disabled{$_} = "cascade";
}
}
}
@tocheckfor = (keys %new_tocheckfor);
}
}
disable(); # First cascade run
our $die = sub { die @_; };
if ($target eq "TABLE") {
local $die = sub { warn @_; };
foreach (sort keys %table) {
print_table_entry($_, "TABLE");
}
exit 0;
}
if ($target eq "LIST") {
foreach (sort keys %table) {
print $_,"\n" unless $table{$_}->{template};
}
exit 0;
}
if ($target eq "HASH") {
local $die = sub { warn @_; };
print "%table = (\n";
foreach (sort keys %table) {
print_table_entry($_, "HASH");
}
exit 0;
}
print "Configuring OpenSSL version $config{full_version} ";
print "for target $target\n";
if (scalar(@seed_sources) == 0) {
print "Using os-specific seed configuration\n";
push @seed_sources, 'os';
}
if (scalar(grep { $_ eq 'egd' } @seed_sources) > 0) {
delete $disabled{'egd'};
}
if (scalar(grep { $_ eq 'none' } @seed_sources) > 0) {
die "Cannot seed with none and anything else" if scalar(@seed_sources) > 1;
warn <<_____ if scalar(@seed_sources) == 1;
============================== WARNING ===============================
You have selected the --with-rand-seed=none option, which effectively
disables automatic reseeding of the OpenSSL random generator.
All operations depending on the random generator such as creating keys
will not work unless the random generator is seeded manually by the
application.
Please read the 'Note on random number generation' section in the
INSTALL.md instructions and the RAND_DRBG(7) manual page for more
details.
============================== WARNING ===============================
_____
}
push @{$config{openssl_feature_defines}},
map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" }
@seed_sources;
# Backward compatibility?
if ($target =~ m/^CygWin32(-.*)$/) {
$target = "Cygwin".$1;
}
# Support for legacy targets having a name starting with 'debug-'
my ($d, $t) = $target =~ m/^(debug-)?(.*)$/;
if ($d) {
$config{build_type} = "debug";
# If we do not find debug-foo in the table, the target is set to foo.
if (!$table{$target}) {
$target = $t;
}
}
if ($target) {
# It's possible that we have different config targets for specific
# toolchains, so we try to detect them, and go for the plain config
# target if not.
my $found;
foreach ( ( "$target-$user{CC}", "$target", undef ) ) {
$found=$_ if $table{$_} && !$table{$_}->{template};
last if $found;
}
$target = $found;
} else {
# If we don't have a config target now, we try the C compiler as we
# fallback
my $cc = $user{CC} // 'cc';
$target = $cc if $table{$cc} && !$table{$cc}->{template};
}
&usage unless $target;
exit 0 if $dryrun; # From older 'config'
$config{target} = $target;
my %target = resolve_config($target);
foreach (keys %target_attr_translate) {
$target{$target_attr_translate{$_}} = $target{$_}
if $target{$_};
delete $target{$_};
}
%target = ( %{$table{DEFAULTS}}, %target );
my %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}});
$config{conf_files} = [ sort keys %conf_files ];
# Using sub disable within these loops may prove fragile, so we run
# a cascade afterwards
foreach my $feature (@{$target{disable}}) {
if (exists $deprecated_disablables{$feature}) {
warn "***** config $target disables deprecated feature $feature\n";
} elsif (!grep { $feature eq $_ } @disablables) {
die "***** config $target disables unknown feature $feature\n";
}
$disabled{$feature} = 'config';
}
foreach my $feature (@{$target{enable}}) {
if ("default" eq ($disabled{$feature} // "")) {
if (exists $deprecated_disablables{$feature}) {
warn "***** config $target enables deprecated feature $feature\n";
} elsif (!grep { $feature eq $_ } @disablables) {
die "***** config $target enables unknown feature $feature\n";
}
delete $disabled{$feature};
}
}
# If uplink_arch isn't defined, disable uplink
$disabled{uplink} = 'no uplink_arch' unless (defined $target{uplink_arch});
# If asm_arch isn't defined, disable asm
$disabled{asm} = 'no asm_arch' unless (defined $target{asm_arch});
disable(); # Run a cascade now
$target{CXXFLAGS}//=$target{CFLAGS} if $target{CXX};
$target{cxxflags}//=$target{cflags} if $target{CXX};
$target{exe_extension}=".exe" if ($config{target} eq "DJGPP");
$target{exe_extension}=".pm" if ($config{target} =~ /vos/);
# Fill %config with values from %user, and in case those are undefined or
# empty, use values from %target (acting as a default).
foreach (keys %user) {
my $ref_type = ref $user{$_};
# Temporary function. Takes an intended ref type (empty string or "ARRAY")
# and a value that's to be coerced into that type.
my $mkvalue = sub {
my $type = shift;
my $value = shift;
my $undef_p = shift;
die "Too many arguments for \$mkvalue" if @_;
while (ref $value eq 'CODE') {
$value = $value->();
}
if ($type eq 'ARRAY') {
return undef unless defined $value;
return undef if ref $value ne 'ARRAY' && !$value;
return undef if ref $value eq 'ARRAY' && !@$value;
return [ $value ] unless ref $value eq 'ARRAY';
}
return undef unless $value;
return $value;
};
$config{$_} =
$mkvalue->($ref_type, $user{$_})
|| $mkvalue->($ref_type, $target{$_});
delete $config{$_} unless defined $config{$_};
}
# Finish up %config by appending things the user gave us on the command line
# apart from "make variables"
foreach (keys %useradd) {
# The must all be lists, so we assert that here
die "internal error: \$useradd{$_} isn't an ARRAY\n"
unless ref $useradd{$_} eq 'ARRAY';
if (defined $config{$_}) {
push @{$config{$_}}, @{$useradd{$_}};
} else {
$config{$_} = [ @{$useradd{$_}} ];
}
}
# At this point, we can forget everything about %user and %useradd,
# because it's now all been merged into the corresponding $config entry
if (grep { $_ =~ /(?:^|\s)-static(?:\s|$)/ } @{$config{LDFLAGS}}) {
disable('static', 'pic', 'threads');
}
# Allow overriding the build file name
$config{build_file} = env('BUILDFILE') || $target{build_file} || "Makefile";
# Make sure build_scheme is consistent.
$target{build_scheme} = [ $target{build_scheme} ]
if ref($target{build_scheme}) ne "ARRAY";
my ($builder, $builder_platform, @builder_opts) =
@{$target{build_scheme}};
foreach my $checker (($builder_platform."-".$config{build_file}."-checker.pm",
$builder_platform."-checker.pm")) {
my $checker_path = catfile($srcdir, "Configurations", $checker);
if (-f $checker_path) {
my $fn = $ENV{CONFIGURE_CHECKER_WARN}
? sub { warn $@; } : sub { die $@; };
if (! do $checker_path) {
if ($@) {
$fn->($@);
} elsif ($!) {
$fn->($!);
} else {
$fn->("The detected tools didn't match the platform\n");
}
}
last;
}
}
push @{$config{defines}}, "NDEBUG" if $config{build_type} eq "release";
if ($target =~ /^mingw/ && `$config{CC} --target-help 2>&1` =~ m/-mno-cygwin/m)
{
push @{$config{cflags}}, "-mno-cygwin";
push @{$config{cxxflags}}, "-mno-cygwin" if $config{CXX};
push @{$config{shared_ldflag}}, "-mno-cygwin";
}
if ($target =~ /linux.*-mips/ && !$disabled{asm}
- && !grep { $_ !~ /-m(ips|arch=)/ } (@{$config{CFLAGS}})) {
+ && !grep { $_ =~ /-m(ips|arch=)/ } (@{$config{CFLAGS}})) {
# minimally required architecture flags for assembly modules
my $value;
$value = '-mips2' if ($target =~ /mips32/);
$value = '-mips3' if ($target =~ /mips64/);
unshift @{$config{cflags}}, $value;
unshift @{$config{cxxflags}}, $value if $config{CXX};
}
# If threads aren't disabled, check how possible they are
unless ($disabled{threads}) {
if ($auto_threads) {
# Enabled by default, disable it forcibly if unavailable
if ($target{thread_scheme} eq "(unknown)") {
disable("unavailable", 'threads');
}
} else {
# The user chose to enable threads explicitly, let's see
# if there's a chance that's possible
if ($target{thread_scheme} eq "(unknown)") {
# If the user asked for "threads" and we don't have internal
# knowledge how to do it, [s]he is expected to provide any
# system-dependent compiler options that are necessary. We
# can't truly check that the given options are correct, but
# we expect the user to know what [s]He is doing.
if (!@{$config{CFLAGS}} && !@{$config{CPPDEFINES}}) {
die "You asked for multi-threading support, but didn't\n"
,"provide any system-specific compiler options\n";
}
}
}
}
# Find out if clang's sanitizers have been enabled with -fsanitize
# flags and ensure that the corresponding %disabled elements area
# removed to reflect that the sanitizers are indeed enabled.
my %detected_sanitizers = ();
foreach (grep /^-fsanitize=/, @{$config{CFLAGS} || []}) {
(my $checks = $_) =~ s/^-fsanitize=//;
foreach (split /,/, $checks) {
my $d = { address => 'asan',
undefined => 'ubsan',
memory => 'msan' } -> {$_};
next unless defined $d;
$detected_sanitizers{$d} = 1;
if (defined $disabled{$d}) {
die "***** Conflict between disabling $d and enabling $_ sanitizer"
if $disabled{$d} ne "default";
delete $disabled{$d};
}
}
}
# If threads still aren't disabled, add a C macro to ensure the source
# code knows about it. Any other flag is taken care of by the configs.
unless($disabled{threads}) {
push @{$config{openssl_feature_defines}}, "OPENSSL_THREADS";
}
my $no_shared_warn=0;
if (($target{shared_target} // '') eq "")
{
$no_shared_warn = 1
if (!$disabled{shared} || !$disabled{"dynamic-engine"});
disable('no-shared-target', 'pic');
}
if ($disabled{"dynamic-engine"}) {
$config{dynamic_engines} = 0;
} else {
$config{dynamic_engines} = 1;
}
unless ($disabled{asan} || defined $detected_sanitizers{asan}) {
push @{$config{cflags}}, "-fsanitize=address";
}
unless ($disabled{ubsan} || defined $detected_sanitizers{ubsan}) {
push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all", "-DPEDANTIC";
}
unless ($disabled{msan} || defined $detected_sanitizers{msan}) {
push @{$config{cflags}}, "-fsanitize=memory";
}
unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"}
&& $disabled{asan} && $disabled{ubsan} && $disabled{msan}) {
push @{$config{cflags}}, "-fno-omit-frame-pointer", "-g";
push @{$config{cxxflags}}, "-fno-omit-frame-pointer", "-g" if $config{CXX};
}
#
# Platform fix-ups
#
# This saves the build files from having to check
if ($disabled{pic})
{
foreach (qw(shared_cflag shared_cxxflag shared_cppflag
shared_defines shared_includes shared_ldflag
module_cflags module_cxxflags module_cppflags
module_defines module_includes module_lflags))
{
delete $config{$_};
$target{$_} = "";
}
}
else
{
push @{$config{lib_defines}}, "OPENSSL_PIC";
}
if ($target{sys_id} ne "")
{
push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}";
}
my %predefined_C = compiler_predefined($config{CROSS_COMPILE}.$config{CC});
my %predefined_CXX = $config{CXX}
? compiler_predefined($config{CROSS_COMPILE}.$config{CXX})
: ();
unless ($disabled{asm}) {
# big endian systems can use ELFv2 ABI
if ($target eq "linux-ppc64") {
$target{perlasm_scheme} = "linux64v2" if ($predefined_C{_CALL_ELF} == 2);
}
}
# Check for makedepend capabilities.
if (!$disabled{makedepend}) {
# If the attribute makedep_scheme is defined, then we assume that the
# config target and its associated build file are programmed to deal
# with it.
# If makedep_scheme is undefined, we go looking for GCC compatible
# dependency making, and if that's not available, we try to fall back
# on 'makedepend'.
if ($target{makedep_scheme}) {
$config{makedep_scheme} = $target{makedep_scheme};
# If the makedepcmd attribute is defined, copy it. If not, the
# build files will have to fend for themselves.
$config{makedepcmd} = $target{makedepcmd} if $target{makedepcmd};
} elsif (($predefined_C{__GNUC__} // -1) >= 3
&& !($predefined_C{__APPLE_CC__} && !$predefined_C{__clang__})) {
# We know that GNU C version 3 and up as well as all clang
# versions support dependency generation, but Xcode did not
# handle $cc -M before clang support (but claims __GNUC__ = 3)
$config{makedep_scheme} = 'gcc';
} else {
# In all other cases, we look for 'makedepend', and set the
# makedep_scheme value if we found it.
$config{makedepcmd} = which('makedepend');
$config{makedep_scheme} = 'makedepend' if $config{makedepcmd};
}
# If no depend scheme is set, we disable makedepend
disable('unavailable', 'makedepend') unless $config{makedep_scheme};
}
if (!$disabled{asm} && !$predefined_C{__MACH__} && $^O ne 'VMS') {
# probe for -Wa,--noexecstack option...
if ($predefined_C{__clang__}) {
# clang has builtin assembler, which doesn't recognize --help,
# but it apparently recognizes the option in question on all
# supported platforms even when it's meaningless. In other words
# probe would fail, but probed option always accepted...
push @{$config{cflags}}, "-Wa,--noexecstack", "-Qunused-arguments";
} else {
my $cc = $config{CROSS_COMPILE}.$config{CC};
open(PIPE, "$cc -Wa,--help -c -o null.$$.o -x assembler /dev/null 2>&1 |");
while(<PIPE>) {
if (m/--noexecstack/) {
push @{$config{cflags}}, "-Wa,--noexecstack";
last;
}
}
close(PIPE);
unlink("null.$$.o");
}
}
# Deal with bn_ops ###################################################
$config{bn_ll} =0;
my $def_int="unsigned int";
$config{rc4_int} =$def_int;
($config{b64l},$config{b64},$config{b32})=(0,0,1);
my $count = 0;
foreach (sort split(/\s+/,$target{bn_ops})) {
$count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/;
$config{bn_ll}=1 if $_ eq 'BN_LLONG';
$config{rc4_int}="unsigned char" if $_ eq 'RC4_CHAR';
($config{b64l},$config{b64},$config{b32})
=(0,1,0) if $_ eq 'SIXTY_FOUR_BIT';
($config{b64l},$config{b64},$config{b32})
=(1,0,0) if $_ eq 'SIXTY_FOUR_BIT_LONG';
($config{b64l},$config{b64},$config{b32})
=(0,0,1) if $_ eq 'THIRTY_TWO_BIT';
}
die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n"
if $count > 1;
$config{api} = $config{major} * 10000 + $config{minor} * 100
unless $config{api};
foreach (keys %$apitable) {
$disabled{"deprecated-$_"} = "deprecation"
if $disabled{deprecated} && $config{api} >= $apitable->{$_};
}
disable(); # Run a cascade now
# Hack cflags for better warnings (dev option) #######################
# "Stringify" the C and C++ flags string. This permits it to be made part of
# a string and works as well on command lines.
$config{cflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
@{$config{cflags}} ];
$config{cxxflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
@{$config{cxxflags}} ] if $config{CXX};
$config{openssl_api_defines} = [
"OPENSSL_CONFIGURED_API=".$config{api},
];
my @strict_warnings_collection=();
if ($strict_warnings)
{
my $wopt;
my $gccver = $predefined_C{__GNUC__} // -1;
if ($gccver >= 4)
{
push @strict_warnings_collection, @gcc_devteam_warn;
push @strict_warnings_collection, @clang_devteam_warn
if (defined($predefined_C{__clang__}));
}
elsif ($config{target} =~ /^VC-/)
{
push @strict_warnings_collection, @cl_devteam_warn;
}
else
{
warn "WARNING --strict-warnings requires gcc[>=4] or gcc-alike, or MSVC"
}
}
$config{CFLAGS} = [ map { $_ eq '--ossl-strict-warnings'
? @strict_warnings_collection
: ( $_ ) }
@{$config{CFLAGS}} ];
unless ($disabled{afalgeng}) {
$config{afalgeng}="";
if (grep { $_ eq 'afalgeng' } @{$target{enable}}) {
my $minver = 4*10000 + 1*100 + 0;
if ($config{CROSS_COMPILE} eq "") {
my $verstr = `uname -r`;
my ($ma, $mi1, $mi2) = split("\\.", $verstr);
($mi2) = $mi2 =~ /(\d+)/;
my $ver = $ma*10000 + $mi1*100 + $mi2;
if ($ver < $minver) {
disable('too-old-kernel', 'afalgeng');
} else {
push @{$config{engdirs}}, "afalg";
}
} else {
disable('cross-compiling', 'afalgeng');
}
} else {
disable('not-linux', 'afalgeng');
}
}
unless ($disabled{devcryptoeng}) {
if ($target =~ m/^BSD/) {
my $maxver = 5*100 + 7;
my $sysstr = `uname -s`;
my $verstr = `uname -r`;
$sysstr =~ s|\R$||;
$verstr =~ s|\R$||;
my ($ma, $mi, @rest) = split m|\.|, $verstr;
my $ver = $ma*100 + $mi;
if ($sysstr eq 'OpenBSD' && $ver >= $maxver) {
disable('too-new-kernel', 'devcryptoeng');
}
}
}
unless ($disabled{ktls}) {
$config{ktls}="";
my $cc = $config{CROSS_COMPILE}.$config{CC};
if ($target =~ m/^linux/) {
system("printf '#include <sys/types.h>\n#include <linux/tls.h>' | $cc -E - >/dev/null 2>&1");
if ($? != 0) {
disable('too-old-kernel', 'ktls');
}
} elsif ($target =~ m/^BSD/) {
system("printf '#include <sys/types.h>\n#include <sys/ktls.h>' | $cc -E - >/dev/null 2>&1");
if ($? != 0) {
disable('too-old-freebsd', 'ktls');
}
} else {
disable('not-linux-or-freebsd', 'ktls');
}
}
push @{$config{openssl_other_defines}}, "OPENSSL_NO_KTLS" if ($disabled{ktls});
# Get the extra flags used when building shared libraries and modules. We
# do this late because some of them depend on %disabled.
# Make the flags to build DSOs the same as for shared libraries unless they
# are already defined
$target{module_cflags} = $target{shared_cflag} unless defined $target{module_cflags};
$target{module_cxxflags} = $target{shared_cxxflag} unless defined $target{module_cxxflags};
$target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_ldflags};
{
my $shared_info_pl =
catfile(dirname($0), "Configurations", "shared-info.pl");
my %shared_info = read_eval_file($shared_info_pl);
push @{$target{_conf_fname_int}}, $shared_info_pl;
my $si = $target{shared_target};
while (ref $si ne "HASH") {
last if ! defined $si;
if (ref $si eq "CODE") {
$si = $si->();
} else {
$si = $shared_info{$si};
}
}
# Some of the 'shared_target' values don't have any entries in
# %shared_info. That's perfectly fine, AS LONG AS the build file
# template knows how to handle this. That is currently the case for
# Windows and VMS.
if (defined $si) {
# Just as above, copy certain shared_* attributes to the corresponding
# module_ attribute unless the latter is already defined
$si->{module_cflags} = $si->{shared_cflag} unless defined $si->{module_cflags};
$si->{module_cxxflags} = $si->{shared_cxxflag} unless defined $si->{module_cxxflags};
$si->{module_ldflags} = $si->{shared_ldflag} unless defined $si->{module_ldflags};
foreach (sort keys %$si) {
$target{$_} = defined $target{$_}
? add($si->{$_})->($target{$_})
: $si->{$_};
}
}
}
# ALL MODIFICATIONS TO %disabled, %config and %target MUST BE DONE FROM HERE ON
######################################################################
# Build up information for skipping certain directories depending on disabled
# features, as well as setting up macros for disabled features.
# This is a tentative database of directories to skip. Some entries may not
# correspond to anything real, but that's ok, they will simply be ignored.
# The actual processing of these entries is done in the build.info lookup
# loop further down.
#
# The key is a Unix formatted path in the source tree, the value is an index
# into %disabled_info, so any existing path gets added to a corresponding
# 'skipped' entry in there with the list of skipped directories.
my %skipdir = ();
my %disabled_info = (); # For configdata.pm
foreach my $what (sort keys %disabled) {
# There are deprecated disablables that translate to themselves.
# They cause disabling cascades, but should otherwise not regiter.
next if $deprecated_disablables{$what};
# The generated $disabled{"deprecated-x.y"} entries are special
# and treated properly elsewhere
next if $what =~ m|^deprecated-|;
$config{options} .= " no-$what";
if (!grep { $what eq $_ } ( 'buildtest-c++', 'fips', 'threads', 'shared',
'module', 'pic', 'dynamic-engine', 'makedepend',
'zlib-dynamic', 'zlib', 'sse2', 'legacy' )) {
(my $WHAT = uc $what) =~ s|-|_|g;
my $skipdir = $what;
# fix-up crypto/directory name(s)
$skipdir = "ripemd" if $what eq "rmd160";
$skipdir = "whrlpool" if $what eq "whirlpool";
my $macro = $disabled_info{$what}->{macro} = "OPENSSL_NO_$WHAT";
push @{$config{openssl_feature_defines}}, $macro;
$skipdir{engines} = $what if $what eq 'engine';
$skipdir{"crypto/$skipdir"} = $what
unless $what eq 'async' || $what eq 'err' || $what eq 'dso';
}
}
if ($disabled{"dynamic-engine"}) {
push @{$config{openssl_feature_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE";
} else {
push @{$config{openssl_feature_defines}}, "OPENSSL_NO_STATIC_ENGINE";
}
# If we use the unified build, collect information from build.info files
my %unified_info = ();
my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO});
if ($builder eq "unified") {
use Text::Template 1.46;
sub cleandir {
my $base = shift;
my $dir = shift;
my $relativeto = shift || ".";
$dir = catdir($base,$dir) unless isabsolute($dir);
# Make sure the directories we're building in exists
mkpath($dir);
my $res = abs2rel(absolutedir($dir), rel2abs($relativeto));
#print STDERR "DEBUG[cleandir]: $dir , $base => $res\n";
return $res;
}
sub cleanfile {
my $base = shift;
my $file = shift;
my $relativeto = shift || ".";
$file = catfile($base,$file) unless isabsolute($file);
my $d = dirname($file);
my $f = basename($file);
# Make sure the directories we're building in exists
mkpath($d);
my $res = abs2rel(catfile(absolutedir($d), $f), rel2abs($relativeto));
#print STDERR "DEBUG[cleanfile]: $d , $f => $res\n";
return $res;
}
# Store the name of the template file we will build the build file from
# in %config. This may be useful for the build file itself.
my @build_file_template_names =
( $builder_platform."-".$config{build_file}.".tmpl",
$config{build_file}.".tmpl" );
my @build_file_templates = ();
# First, look in the user provided directory, if given
if (defined env($local_config_envname)) {
@build_file_templates =
map {
if ($^O eq 'VMS') {
# VMS environment variables are logical names,
# which can be used as is
$local_config_envname . ':' . $_;
} else {
catfile(env($local_config_envname), $_);
}
}
@build_file_template_names;
}
# Then, look in our standard directory
push @build_file_templates,
( map { cleanfile($srcdir, catfile("Configurations", $_), $blddir) }
@build_file_template_names );
my $build_file_template;
for $_ (@build_file_templates) {
$build_file_template = $_;
last if -f $build_file_template;
$build_file_template = undef;
}
if (!defined $build_file_template) {
die "*** Couldn't find any of:\n", join("\n", @build_file_templates), "\n";
}
$config{build_file_templates}
= [ cleanfile($srcdir, catfile("Configurations", "common0.tmpl"),
$blddir),
$build_file_template ];
my @build_dirs = ( [ ] ); # current directory
$config{build_infos} = [ ];
# We want to detect configdata.pm in the source tree, so we
# don't use it if the build tree is different.
my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir);
# Any source file that we recognise is placed in this hash table, with
# the list of its intended destinations as value. When everything has
# been collected, there's a routine that checks that these source files
# exist, or if they are generated, that the generator exists.
my %check_exist = ();
my %check_generate = ();
my %ordinals = ();
while (@build_dirs) {
my @curd = @{shift @build_dirs};
my $sourced = catdir($srcdir, @curd);
my $buildd = catdir($blddir, @curd);
my $unixdir = join('/', @curd);
if (exists $skipdir{$unixdir}) {
my $what = $skipdir{$unixdir};
push @{$disabled_info{$what}->{skipped}}, catdir(@curd);
next;
}
mkpath($buildd);
my $f = 'build.info';
# The basic things we're trying to build
my @programs = ();
my @libraries = ();
my @modules = ();
my @scripts = ();
my %sources = ();
my %shared_sources = ();
my %includes = ();
my %defines = ();
my %depends = ();
my %generate = ();
my %imagedocs = ();
my %htmldocs = ();
my %mandocs = ();
# Support for $variablename in build.info files.
# Embedded perl code is the ultimate master, still. If its output
# contains a dollar sign, it had better be escaped, or it will be
# taken for a variable name prefix.
my %variables = ();
# Variable name syntax
my $variable_name_re = qr/(?P<VARIABLE>[[:alpha:]][[:alnum:]_]*)/;
# Value modifier syntaxes
my $variable_subst_re = qr/\/(?P<RE>(?:\\\/|.)*?)\/(?P<SUBST>.*?)/;
# Variable reference
my $variable_simple_re = qr/(?<!\\)\$${variable_name_re}/;
my $variable_w_mod_re =
qr/(?<!\\)\$\{${variable_name_re}(?P<MOD>(?:\\\/|.)*?)\}/;
# Tie it all together
my $variable_re = qr/${variable_simple_re}|${variable_w_mod_re}/;
my $expand_variables = sub {
my $value = '';
my $value_rest = shift;
if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) {
print STDERR
"DEBUG[\$expand_variables] Parsed '$value_rest' ...\n"
}
while ($value_rest =~ /${variable_re}/) {
# We must save important regexp values, because the next
# regexp clears them
my $mod = $+{MOD};
my $variable_value = $variables{$+{VARIABLE}};
$value_rest = $';
$value .= $`;
# Process modifier expressions, if present
if (defined $mod) {
if ($mod =~ /^${variable_subst_re}$/) {
my $re = $+{RE};
my $subst = $+{SUBST};
$variable_value =~ s/\Q$re\E/$subst/g;
if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) {
print STDERR
"DEBUG[\$expand_variables] ... and substituted ",
"'$re' with '$subst'\n";
}
}
}
$value .= $variable_value;
}
if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) {
print STDERR
"DEBUG[\$expand_variables] ... into: '$value$value_rest'\n";
}
return $value . $value_rest;
};
# Support for attributes in build.info files
my %attributes = ();
my $handle_attributes = sub {
my $attr_str = shift;
my $ref = shift;
my @goals = @_;
return unless defined $attr_str;
my @a = tokenize($attr_str, qr|\s*,\s*|);
foreach my $a (@a) {
my $ac = 1;
my $ak = $a;
my $av = 1;
if ($a =~ m|^(!)?(.*?)\s* = \s*(.*?)$|x) {
$ac = ! $1;
$ak = $2;
$av = $3;
}
foreach my $g (@goals) {
if ($ac) {
$$ref->{$g}->{$ak} = $av;
} else {
delete $$ref->{$g}->{$ak};
}
}
}
};
# Support for pushing values on multiple indexes of a given hash
# array.
my $push_to = sub {
my $valueref = shift;
my $index_str = shift; # May be undef or empty
my $attrref = shift; # May be undef
my $attr_str = shift;
my @values = @_;
if (defined $index_str) {
my @indexes = ( '' );
if ($index_str !~ m|^\s*$|) {
@indexes = tokenize($index_str);
}
foreach (@indexes) {
push @{$valueref->{$_}}, @values;
if (defined $attrref) {
$handle_attributes->($attr_str, \$$attrref->{$_},
@values);
}
}
} else {
push @$valueref, @values;
$handle_attributes->($attr_str, $attrref, @values)
if defined $attrref;
}
};
if ($buildinfo_debug) {
print STDERR "DEBUG: Reading ",catfile($sourced, $f),"\n";
}
push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f);
my $template =
Text::Template->new(TYPE => 'FILE',
SOURCE => catfile($sourced, $f),
PREPEND => qq{use lib "$FindBin::Bin/util/perl";});
die "Something went wrong with $sourced/$f: $!\n" unless $template;
my @text =
split /^/m,
$template->fill_in(HASH => { config => \%config,
target => \%target,
disabled => \%disabled,
withargs => \%withargs,
builddir => abs2rel($buildd, $blddir),
sourcedir => abs2rel($sourced, $blddir),
buildtop => abs2rel($blddir, $blddir),
sourcetop => abs2rel($srcdir, $blddir) },
DELIMITERS => [ "{-", "-}" ]);
# The top item of this stack has the following values
# -2 positive already run and we found ELSE (following ELSIF should fail)
# -1 positive already run (skip until ENDIF)
# 0 negatives so far (if we're at a condition, check it)
# 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF)
# 2 positive ELSE (following ELSIF should fail)
my @skip = ();
# A few useful generic regexps
my $index_re = qr/\[\s*(?P<INDEX>(?:\\.|.)*?)\s*\]/;
my $cond_re = qr/\[\s*(?P<COND>(?:\\.|.)*?)\s*\]/;
my $attribs_re = qr/(?:\{\s*(?P<ATTRIBS>(?:\\.|.)*?)\s*\})?/;
my $value_re = qr/(?P<VALUE>.*?)/;
collect_information(
collect_from_array([ @text ],
qr/\\$/ => sub { my $l1 = shift; my $l2 = shift;
$l1 =~ s/\\$//; $l1.$l2 }),
# Info we're looking for
qr/^\s* IF ${cond_re} \s*$/x
=> sub {
if (! @skip || $skip[$#skip] > 0) {
push @skip, !! $expand_variables->($+{COND});
} else {
push @skip, -1;
}
},
qr/^\s* ELSIF ${cond_re} \s*$/x
=> sub { die "ELSIF out of scope" if ! @skip;
die "ELSIF following ELSE" if abs($skip[$#skip]) == 2;
$skip[$#skip] = -1 if $skip[$#skip] != 0;
$skip[$#skip] = !! $expand_variables->($+{COND})
if $skip[$#skip] == 0; },
qr/^\s* ELSE \s*$/x
=> sub { die "ELSE out of scope" if ! @skip;
$skip[$#skip] = -2 if $skip[$#skip] != 0;
$skip[$#skip] = 2 if $skip[$#skip] == 0; },
qr/^\s* ENDIF \s*$/x
=> sub { die "ENDIF out of scope" if ! @skip;
pop @skip; },
qr/^\s* ${variable_re} \s* = \s* ${value_re} \s* $/x
=> sub {
if (!@skip || $skip[$#skip] > 0) {
$variables{$+{VARIABLE}} = $expand_variables->($+{VALUE});
}
},
qr/^\s* SUBDIRS \s* = \s* ${value_re} \s* $/x
=> sub {
if (!@skip || $skip[$#skip] > 0) {
foreach (tokenize($expand_variables->($+{VALUE}))) {
push @build_dirs, [ @curd, splitdir($_, 1) ];
}
}
},
qr/^\s* PROGRAMS ${attribs_re} \s* = \s* ${value_re} \s* $/x
=> sub { $push_to->(\@programs, undef,
\$attributes{programs}, $+{ATTRIBS},
tokenize($expand_variables->($+{VALUE})))
if !@skip || $skip[$#skip] > 0; },
qr/^\s* LIBS ${attribs_re} \s* = \s* ${value_re} \s* $/x
=> sub { $push_to->(\@libraries, undef,
\$attributes{libraries}, $+{ATTRIBS},
tokenize($expand_variables->($+{VALUE})))
if !@skip || $skip[$#skip] > 0; },
qr/^\s* MODULES ${attribs_re} \s* = \s* ${value_re} \s* $/x
=> sub { $push_to->(\@modules, undef,
\$attributes{modules}, $+{ATTRIBS},
tokenize($expand_variables->($+{VALUE})))
if !@skip || $skip[$#skip] > 0; },
qr/^\s* SCRIPTS ${attribs_re} \s* = \s* ${value_re} \s* $/x
=> sub { $push_to->(\@scripts, undef,
\$attributes{scripts}, $+{ATTRIBS},
tokenize($expand_variables->($+{VALUE})))
if !@skip || $skip[$#skip] > 0; },
qr/^\s* IMAGEDOCS ${index_re} \s* = \s* ${value_re} \s* $/x
=> sub { $push_to->(\%imagedocs, $expand_variables->($+{INDEX}),
undef, undef,
tokenize($expand_variables->($+{VALUE})))
if !@skip || $skip[$#skip] > 0; },
qr/^\s* HTMLDOCS ${index_re} \s* = \s* ${value_re} \s* $/x
=> sub { $push_to->(\%htmldocs, $expand_variables->($+{INDEX}),
undef, undef,
tokenize($expand_variables->($+{VALUE})))
if !@skip || $skip[$#skip] > 0; },
qr/^\s* MANDOCS ${index_re} \s* = \s* ${value_re} \s* $/x
=> sub { $push_to->(\%mandocs, $expand_variables->($+{INDEX}),
undef, undef,
tokenize($expand_variables->($+{VALUE})))
if !@skip || $skip[$#skip] > 0; },
qr/^\s* SOURCE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x
=> sub { $push_to->(\%sources, $expand_variables->($+{INDEX}),
\$attributes{sources}, $+{ATTRIBS},
tokenize($expand_variables->($+{VALUE})))
if !@skip || $skip[$#skip] > 0; },
qr/^\s* SHARED_SOURCE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x
=> sub { $push_to->(\%shared_sources, $expand_variables->($+{INDEX}),
\$attributes{sources}, $+{ATTRIBS},
tokenize($expand_variables->($+{VALUE})))
if !@skip || $skip[$#skip] > 0; },
qr/^\s* INCLUDE ${index_re} \s* = \s* ${value_re} \s* $/x
=> sub { $push_to->(\%includes, $expand_variables->($+{INDEX}),
undef, undef,
tokenize($expand_variables->($+{VALUE})))
if !@skip || $skip[$#skip] > 0; },
qr/^\s* DEFINE ${index_re} \s* = \s* ${value_re} \s* $/x
=> sub { $push_to->(\%defines, $expand_variables->($+{INDEX}),
undef, undef,
tokenize($expand_variables->($+{VALUE})))
if !@skip || $skip[$#skip] > 0; },
qr/^\s* DEPEND ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x
=> sub { $push_to->(\%depends, $expand_variables->($+{INDEX}),
\$attributes{depends}, $+{ATTRIBS},
tokenize($expand_variables->($+{VALUE})))
if !@skip || $skip[$#skip] > 0; },
qr/^\s* GENERATE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x
=> sub { $push_to->(\%generate, $expand_variables->($+{INDEX}),
\$attributes{generate}, $+{ATTRIBS},
$expand_variables->($+{VALUE}))
if !@skip || $skip[$#skip] > 0; },
qr/^\s* (?:\#.*)? $/x => sub { },
"OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" },
"BEFORE" => sub {
if ($buildinfo_debug) {
print STDERR "DEBUG: Parsing ",join(" ", @_),"\n";
print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
}
},
"AFTER" => sub {
if ($buildinfo_debug) {
print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
}
},
);
die "runaway IF?" if (@skip);
if (grep { defined $attributes{modules}->{$_}->{engine} } keys %attributes
and !$config{dynamic_engines}) {
die <<"EOF"
ENGINES can only be used if configured with 'dynamic-engine'.
This is usually a fault in a build.info file.
EOF
}
{
my %infos = ( programs => [ @programs ],
libraries => [ @libraries ],
modules => [ @modules ],
scripts => [ @scripts ] );
foreach my $k (keys %infos) {
foreach (@{$infos{$k}}) {
my $item = cleanfile($buildd, $_, $blddir);
$unified_info{$k}->{$item} = 1;
# Fix up associated attributes
$unified_info{attributes}->{$k}->{$item} =
$attributes{$k}->{$_}
if defined $attributes{$k}->{$_};
}
}
}
# Check that we haven't defined any library as both shared and
# explicitly static. That is forbidden.
my @doubles = ();
foreach (grep /\.a$/, keys %{$unified_info{libraries}}) {
(my $l = $_) =~ s/\.a$//;
push @doubles, $l if defined $unified_info{libraries}->{$l};
}
die "these libraries are both explicitly static and shared:\n ",
join(" ", @doubles), "\n"
if @doubles;
foreach (keys %sources) {
my $dest = $_;
my $ddest = cleanfile($buildd, $_, $blddir);
foreach (@{$sources{$dest}}) {
my $s = cleanfile($sourced, $_, $blddir);
# If it's generated or we simply don't find it in the source
# tree, we assume it's in the build tree.
if ($s eq $src_configdata || $generate{$_} || ! -f $s) {
$s = cleanfile($buildd, $_, $blddir);
}
my $o = $_;
# We recognise C++, C and asm files
if ($s =~ /\.(cc|cpp|c|s|S)$/) {
push @{$check_exist{$s}}, $ddest;
$o =~ s/\.[csS]$/.o/; # C and assembler
$o =~ s/\.(cc|cpp)$/_cc.o/; # C++
$o = cleanfile($buildd, $o, $blddir);
$unified_info{sources}->{$ddest}->{$o} = -1;
$unified_info{sources}->{$o}->{$s} = -1;
} elsif ($s =~ /\.rc$/) {
# We also recognise resource files
push @{$check_exist{$s}}, $ddest;
$o =~ s/\.rc$/.res/; # Resource configuration
$o = cleanfile($buildd, $o, $blddir);
$unified_info{sources}->{$ddest}->{$o} = -1;
$unified_info{sources}->{$o}->{$s} = -1;
} else {
push @{$check_exist{$s}}, $ddest;
$unified_info{sources}->{$ddest}->{$s} = 1;
}
# Fix up associated attributes
if ($o ne $_) {
$unified_info{attributes}->{sources}->{$ddest}->{$o} =
$unified_info{attributes}->{sources}->{$o}->{$s} =
$attributes{sources}->{$dest}->{$_}
if defined $attributes{sources}->{$dest}->{$_};
} else {
$unified_info{attributes}->{sources}->{$ddest}->{$s} =
$attributes{sources}->{$dest}->{$_}
if defined $attributes{sources}->{$dest}->{$_};
}
}
}
foreach (keys %shared_sources) {
my $dest = $_;
my $ddest = cleanfile($buildd, $_, $blddir);
foreach (@{$shared_sources{$dest}}) {
my $s = cleanfile($sourced, $_, $blddir);
# If it's generated or we simply don't find it in the source
# tree, we assume it's in the build tree.
if ($s eq $src_configdata || $generate{$_} || ! -f $s) {
$s = cleanfile($buildd, $_, $blddir);
}
my $o = $_;
if ($s =~ /\.(cc|cpp|c|s|S)$/) {
# We recognise C++, C and asm files
push @{$check_exist{$s}}, $ddest;
$o =~ s/\.[csS]$/.o/; # C and assembler
$o =~ s/\.(cc|cpp)$/_cc.o/; # C++
$o = cleanfile($buildd, $o, $blddir);
$unified_info{shared_sources}->{$ddest}->{$o} = -1;
$unified_info{sources}->{$o}->{$s} = -1;
} elsif ($s =~ /\.rc$/) {
# We also recognise resource files
push @{$check_exist{$s}}, $ddest;
$o =~ s/\.rc$/.res/; # Resource configuration
$o = cleanfile($buildd, $o, $blddir);
$unified_info{shared_sources}->{$ddest}->{$o} = -1;
$unified_info{sources}->{$o}->{$s} = -1;
} elsif ($s =~ /\.ld$/) {
# We also recognise linker scripts (or corresponding)
# We know they are generated files
push @{$check_exist{$s}}, $ddest;
$o = cleanfile($buildd, $_, $blddir);
$unified_info{shared_sources}->{$ddest}->{$o} = 1;
} else {
die "unrecognised source file type for shared library: $s\n";
}
# Fix up associated attributes
if ($o ne $_) {
$unified_info{attributes}->{shared_sources}->{$ddest}->{$o} =
$unified_info{attributes}->{sources}->{$o}->{$s} =
$attributes{sources}->{$dest}->{$_}
if defined $attributes{sources}->{$dest}->{$_};
} else {
$unified_info{attributes}->{shared_sources}->{$ddest}->{$o} =
$attributes{sources}->{$dest}->{$_}
if defined $attributes{sources}->{$dest}->{$_};
}
}
}
foreach (keys %generate) {
my $dest = $_;
my $ddest = cleanfile($buildd, $_, $blddir);
die "more than one generator for $dest: "
,join(" ", @{$generate{$_}}),"\n"
if scalar @{$generate{$_}} > 1;
my @generator = split /\s+/, $generate{$dest}->[0];
my $gen = $generator[0];
$generator[0] = cleanfile($sourced, $gen, $blddir);
# If the generator is itself generated, it's in the build tree
if ($generate{$gen} || ! -f $generator[0]) {
$generator[0] = cleanfile($buildd, $gen, $blddir);
}
$check_generate{$ddest}->{$generator[0]}++;
$unified_info{generate}->{$ddest} = [ @generator ];
# Fix up associated attributes
$unified_info{attributes}->{generate}->{$ddest} =
$attributes{generate}->{$dest}->{$gen}
if defined $attributes{generate}->{$dest}->{$gen};
}
foreach (keys %depends) {
my $dest = $_;
my $ddest = $dest;
if ($dest =~ /^\|(.*)\|$/) {
# Collect the raw target
$unified_info{targets}->{$1} = 1;
$ddest = $1;
} elsif ($dest eq '') {
$ddest = '';
} else {
$ddest = cleanfile($sourced, $_, $blddir);
# If the destination doesn't exist in source, it can only be
# a generated file in the build tree.
if ($ddest eq $src_configdata || ! -f $ddest) {
$ddest = cleanfile($buildd, $_, $blddir);
}
}
foreach (@{$depends{$dest}}) {
my $d = cleanfile($sourced, $_, $blddir);
my $d2 = cleanfile($buildd, $_, $blddir);
# If we know it's generated, or assume it is because we can't
# find it in the source tree, we set file we depend on to be
# in the build tree rather than the source tree.
if ($d eq $src_configdata
|| (grep { $d2 eq $_ }
keys %{$unified_info{generate}})
|| ! -f $d) {
$d = $d2;
}
$unified_info{depends}->{$ddest}->{$d} = 1;
# Fix up associated attributes
$unified_info{attributes}->{depends}->{$ddest}->{$d} =
$attributes{depends}->{$dest}->{$_}
if defined $attributes{depends}->{$dest}->{$_};
}
}
foreach (keys %includes) {
my $dest = $_;
my $ddest = cleanfile($sourced, $_, $blddir);
# If the destination doesn't exist in source, it can only be
# a generated file in the build tree.
if ($ddest eq $src_configdata || ! -f $ddest) {
$ddest = cleanfile($buildd, $_, $blddir);
}
foreach (@{$includes{$dest}}) {
my $is = cleandir($sourced, $_, $blddir);
my $ib = cleandir($buildd, $_, $blddir);
push @{$unified_info{includes}->{$ddest}->{source}}, $is
unless grep { $_ eq $is } @{$unified_info{includes}->{$ddest}->{source}};
push @{$unified_info{includes}->{$ddest}->{build}}, $ib
unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}};
}
}
foreach my $dest (keys %defines) {
my $ddest;
if ($dest ne "") {
$ddest = cleanfile($sourced, $dest, $blddir);
# If the destination doesn't exist in source, it can only
# be a generated file in the build tree.
if (! -f $ddest) {
$ddest = cleanfile($buildd, $dest, $blddir);
}
}
foreach my $v (@{$defines{$dest}}) {
$v =~ m|^([^=]*)(=.*)?$|;
die "0 length macro name not permitted\n" if $1 eq "";
if ($dest ne "") {
die "$1 defined more than once\n"
if defined $unified_info{defines}->{$ddest}->{$1};
$unified_info{defines}->{$ddest}->{$1} = $2;
} else {
die "$1 defined more than once\n"
if grep { $v eq $_ } @{$config{defines}};
push @{$config{defines}}, $v;
}
}
}
foreach my $section (keys %imagedocs) {
foreach (@{$imagedocs{$section}}) {
my $imagedocs = cleanfile($buildd, $_, $blddir);
$unified_info{imagedocs}->{$section}->{$imagedocs} = 1;
}
}
foreach my $section (keys %htmldocs) {
foreach (@{$htmldocs{$section}}) {
my $htmldocs = cleanfile($buildd, $_, $blddir);
$unified_info{htmldocs}->{$section}->{$htmldocs} = 1;
}
}
foreach my $section (keys %mandocs) {
foreach (@{$mandocs{$section}}) {
my $mandocs = cleanfile($buildd, $_, $blddir);
$unified_info{mandocs}->{$section}->{$mandocs} = 1;
}
}
}
my $ordinals_text = join(', ', sort keys %ordinals);
warn <<"EOF" if $ordinals_text;
WARNING: ORDINALS were specified for $ordinals_text
They are ignored and should be replaced with a combination of GENERATE,
DEPEND and SHARED_SOURCE.
EOF
# Check that each generated file is only generated once
my $ambiguous_generation = 0;
foreach (sort keys %check_generate) {
my @generators = sort keys %{$check_generate{$_}};
my $generators_txt = join(', ', @generators);
if (scalar @generators > 1) {
warn "$_ is GENERATEd by more than one generator ($generators_txt)\n";
$ambiguous_generation++;
}
if ($check_generate{$_}->{$generators[0]} > 1) {
warn "INFO: $_ has more than one GENERATE declaration (same generator)\n"
}
}
die "There are ambiguous source file generations\n"
if $ambiguous_generation > 0;
# All given source files should exist, or if generated, their
# generator should exist. This loop ensures this is true.
my $missing = 0;
foreach my $orig (sort keys %check_exist) {
foreach my $dest (@{$check_exist{$orig}}) {
if ($orig ne $src_configdata) {
if ($orig =~ /\.a$/) {
# Static library names may be used as sources, so we
# need to detect those and give them special treatment.
unless (grep { $_ eq $orig }
keys %{$unified_info{libraries}}) {
warn "$orig is given as source for $dest, but no such library is built\n";
$missing++;
}
} else {
# A source may be generated, and its generator may be
# generated as well. We therefore loop to dig out the
# first generator.
my $gen = $orig;
while (my @next = keys %{$check_generate{$gen}}) {
$gen = $next[0];
}
if (! -f $gen) {
if ($gen ne $orig) {
$missing++;
warn "$orig is given as source for $dest, but its generator (leading to $gen) is missing\n";
} else {
$missing++;
warn "$orig is given as source for $dest, but is missing\n";
}
}
}
}
}
}
die "There are files missing\n" if $missing > 0;
# Go through the sources of all libraries and check that the same basename
# doesn't appear more than once. Some static library archivers depend on
# them being unique.
{
my $err = 0;
foreach my $prod (keys %{$unified_info{libraries}}) {
my @prod_sources =
map { keys %{$unified_info{sources}->{$_}} }
keys %{$unified_info{sources}->{$prod}};
my %srccnt = ();
# Count how many times a given each source basename
# appears for each product.
foreach my $src (@prod_sources) {
$srccnt{basename $src}++;
}
foreach my $src (keys %srccnt) {
if ((my $cnt = $srccnt{$src}) > 1) {
print STDERR "$src appears $cnt times for the product $prod\n";
$err++
}
}
}
die if $err > 0;
}
# Massage the result
# If we depend on a header file or a perl module, add an inclusion of
# its directory to allow smoothe inclusion
foreach my $dest (keys %{$unified_info{depends}}) {
next if $dest eq "";
foreach my $d (keys %{$unified_info{depends}->{$dest}}) {
next unless $d =~ /\.(h|pm)$/;
my $i = dirname($d);
my $spot =
$d eq "configdata.pm" || defined($unified_info{generate}->{$d})
? 'build' : 'source';
push @{$unified_info{includes}->{$dest}->{$spot}}, $i
unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{$spot}};
}
}
# Go through all intermediary files and change their names to something that
# reflects what they will be built for. Note that for some source files,
# this leads to duplicate object files because they are used multiple times.
# the goal is to rename all object files according to this scheme:
# {productname}-{midfix}-{origobjname}.[o|res]
# the {midfix} is a keyword indicating the type of product, which is mostly
# valuable for libraries since they come in two forms.
#
# This also reorganises the {sources} and {shared_sources} so that the
# former only contains ALL object files that are supposed to end up in
# static libraries and programs, while the latter contains ALL object files
# that are supposed to end up in shared libraries and DSOs.
# The main reason for having two different source structures is to allow
# the same name to be used for the static and the shared variants of a
# library.
{
# Take copies so we don't get interference from added stuff
my %unified_copy = ();
foreach (('sources', 'shared_sources')) {
$unified_copy{$_} = { %{$unified_info{$_}} }
if defined($unified_info{$_});
delete $unified_info{$_};
}
foreach my $prodtype (('programs', 'libraries', 'modules', 'scripts')) {
# $intent serves multi purposes:
# - give a prefix for the new object files names
# - in the case of libraries, rearrange the object files so static
# libraries use the 'sources' structure exclusively, while shared
# libraries use the 'shared_sources' structure exclusively.
my $intent = {
programs => { bin => { src => [ 'sources' ],
dst => 'sources' } },
libraries => { lib => { src => [ 'sources' ],
dst => 'sources' },
shlib => { prodselect =>
sub { grep !/\.a$/, @_ },
src => [ 'sources',
'shared_sources' ],
dst => 'shared_sources' } },
modules => { dso => { src => [ 'sources' ],
dst => 'sources' } },
scripts => { script => { src => [ 'sources' ],
dst => 'sources' } }
} -> {$prodtype};
foreach my $kind (keys %$intent) {
next if ($intent->{$kind}->{dst} eq 'shared_sources'
&& $disabled{shared});
my @src = @{$intent->{$kind}->{src}};
my $dst = $intent->{$kind}->{dst};
my $prodselect = $intent->{$kind}->{prodselect} // sub { @_ };
foreach my $prod ($prodselect->(keys %{$unified_info{$prodtype}})) {
# %prod_sources has all applicable objects as keys, and
# their corresponding sources as values
my %prod_sources =
map { $_ => [ keys %{$unified_copy{sources}->{$_}} ] }
map { keys %{$unified_copy{$_}->{$prod}} }
@src;
foreach (keys %prod_sources) {
# Only affect object files and resource files,
# the others simply get a new value
# (+1 instead of -1)
if ($_ =~ /\.(o|res)$/) {
(my $prodname = $prod) =~ s|\.a$||;
my $newobj =
catfile(dirname($_),
basename($prodname)
. '-' . $kind
. '-' . basename($_));
$unified_info{$dst}->{$prod}->{$newobj} = 1;
foreach my $src (@{$prod_sources{$_}}) {
$unified_info{sources}->{$newobj}->{$src} = 1;
# Adjust source attributes
my $attrs = $unified_info{attributes}->{sources};
if (defined $attrs->{$prod}
&& defined $attrs->{$prod}->{$_}) {
$attrs->{$prod}->{$newobj} =
$attrs->{$prod}->{$_};
delete $attrs->{$prod}->{$_};
}
foreach my $objsrc (keys %{$attrs->{$_} // {}}) {
$attrs->{$newobj}->{$objsrc} =
$attrs->{$_}->{$objsrc};
delete $attrs->{$_}->{$objsrc};
}
}
# Adjust dependencies
foreach my $deps (keys %{$unified_info{depends}->{$_}}) {
$unified_info{depends}->{$_}->{$deps} = -1;
$unified_info{depends}->{$newobj}->{$deps} = 1;
}
# Adjust includes
foreach my $k (('source', 'build')) {
next unless
defined($unified_info{includes}->{$_}->{$k});
my @incs = @{$unified_info{includes}->{$_}->{$k}};
$unified_info{includes}->{$newobj}->{$k} = [ @incs ];
}
} else {
$unified_info{$dst}->{$prod}->{$_} = 1;
}
}
}
}
}
}
# At this point, we have a number of sources with the value -1. They
# aren't part of the local build and are probably meant for a different
# platform, and can therefore be cleaned away. That happens when making
# %unified_info more efficient below.
### Make unified_info a bit more efficient
# One level structures
foreach (("programs", "libraries", "modules", "scripts", "targets")) {
$unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
}
# Two level structures
foreach my $l1 (("sources", "shared_sources", "ldadd", "depends",
"imagedocs", "htmldocs", "mandocs")) {
foreach my $l2 (sort keys %{$unified_info{$l1}}) {
my @items =
sort
grep { $unified_info{$l1}->{$l2}->{$_} > 0 }
keys %{$unified_info{$l1}->{$l2}};
if (@items) {
$unified_info{$l1}->{$l2} = [ @items ];
} else {
delete $unified_info{$l1}->{$l2};
}
}
}
# Defines
foreach my $dest (sort keys %{$unified_info{defines}}) {
$unified_info{defines}->{$dest}
= [ map { $_.$unified_info{defines}->{$dest}->{$_} }
sort keys %{$unified_info{defines}->{$dest}} ];
}
# Includes
foreach my $dest (sort keys %{$unified_info{includes}}) {
if (defined($unified_info{includes}->{$dest}->{build})) {
my @source_includes = ();
@source_includes = ( @{$unified_info{includes}->{$dest}->{source}} )
if defined($unified_info{includes}->{$dest}->{source});
$unified_info{includes}->{$dest} =
[ @{$unified_info{includes}->{$dest}->{build}} ];
foreach my $inc (@source_includes) {
push @{$unified_info{includes}->{$dest}}, $inc
unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}};
}
} elsif (defined($unified_info{includes}->{$dest}->{source})) {
$unified_info{includes}->{$dest} =
[ @{$unified_info{includes}->{$dest}->{source}} ];
} else {
delete $unified_info{includes}->{$dest};
}
}
# For convenience collect information regarding directories where
# files are generated, those generated files and the end product
# they end up in where applicable. Then, add build rules for those
# directories
my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ],
"dso" => [ @{$unified_info{modules}} ],
"bin" => [ @{$unified_info{programs}} ],
"script" => [ @{$unified_info{scripts}} ],
"docs" => [ (map { @{$unified_info{imagedocs}->{$_} // []} }
keys %{$unified_info{imagedocs} // {}}),
(map { @{$unified_info{htmldocs}->{$_} // []} }
keys %{$unified_info{htmldocs} // {}}),
(map { @{$unified_info{mandocs}->{$_} // []} }
keys %{$unified_info{mandocs} // {}}) ] );
foreach my $type (sort keys %loopinfo) {
foreach my $product (@{$loopinfo{$type}}) {
my %dirs = ();
my $pd = dirname($product);
foreach (@{$unified_info{sources}->{$product} // []},
@{$unified_info{shared_sources}->{$product} // []}) {
my $d = dirname($_);
# We don't want to create targets for source directories
# when building out of source
next if ($config{sourcedir} ne $config{builddir}
&& $d =~ m|^\Q$config{sourcedir}\E|);
# We already have a "test" target, and the current directory
# is just silly to make a target for
next if $d eq "test" || $d eq ".";
$dirs{$d} = 1;
push @{$unified_info{dirinfo}->{$d}->{deps}}, $_
if $d ne $pd;
}
foreach (sort keys %dirs) {
push @{$unified_info{dirinfo}->{$_}->{products}->{$type}},
$product;
}
}
}
}
# For the schemes that need it, we provide the old *_obj configs
# from the *_asm_obj ones
foreach (grep /_(asm|aux)_src$/, keys %target) {
my $src = $_;
(my $obj = $_) =~ s/_(asm|aux)_src$/_obj/;
$target{$obj} = $target{$src};
$target{$obj} =~ s/\.[csS]\b/.o/g; # C and assembler
$target{$obj} =~ s/\.(cc|cpp)\b/_cc.o/g; # C++
}
# Write down our configuration where it fits #########################
my %template_vars = (
config => \%config,
target => \%target,
disablables => \@disablables,
disablables_int => \@disablables_int,
disabled => \%disabled,
withargs => \%withargs,
unified_info => \%unified_info,
tls => \@tls,
dtls => \@dtls,
makevars => [ sort keys %user ],
disabled_info => \%disabled_info,
user_crossable => \@user_crossable,
);
my $configdata_outname = 'configdata.pm';
open CONFIGDATA, ">$configdata_outname.new"
or die "Trying to create $configdata_outname.new: $!";
my $configdata_tmplname = cleanfile($srcdir, "configdata.pm.in", $blddir);
my $configdata_tmpl =
OpenSSL::Template->new(TYPE => 'FILE', SOURCE => $configdata_tmplname);
$configdata_tmpl->fill_in(
FILENAME => $configdata_tmplname,
OUTPUT => \*CONFIGDATA,
HASH => { %template_vars,
autowarntext => [
'WARNING: do not edit!',
"Generated by Configure from $configdata_tmplname",
] }
) or die $Text::Template::ERROR;
close CONFIGDATA;
rename "$configdata_outname.new", $configdata_outname;
if ($builder_platform eq 'unix') {
my $mode = (0755 & ~umask);
chmod $mode, 'configdata.pm'
or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!);
}
print "Created $configdata_outname\n";
print "Running $configdata_outname\n";
my $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
my $cmd = "$perlcmd $configdata_outname";
#print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
system($cmd);
exit 1 if $? != 0;
$SIG{__DIE__} = $orig_death_handler;
print <<"EOF" if ($disabled{threads} eq "unavailable");
The library could not be configured for supporting multi-threaded
applications as the compiler options required on this system are not known.
See file INSTALL.md for details if you need multi-threading.
EOF
print <<"EOF" if ($no_shared_warn);
The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this
platform, so we will pretend you gave the option 'no-pic', which also disables
'shared' and 'dynamic-engine'. If you know how to implement shared libraries
or position independent code, please let us know (but please first make sure
you have tried with a current version of OpenSSL).
EOF
print $banner;
exit(0);
######################################################################
#
# Helpers and utility functions
#
# Death handler, to print a helpful message in case of failure #######
#
sub death_handler {
die @_ if $^S; # To prevent the added message in eval blocks
my $build_file = $config{build_file} // "build file";
my @message = ( <<"_____", @_ );
Failure! $build_file wasn't produced.
Please read INSTALL.md and associated NOTES-* files. You may also have to
look over your available compiler tool chain or change your configuration.
_____
# Dying is terminal, so it's ok to reset the signal handler here.
$SIG{__DIE__} = $orig_death_handler;
die @message;
}
# Configuration file reading #########################################
# Note: All of the helper functions are for lazy evaluation. They all
# return a CODE ref, which will return the intended value when evaluated.
# Thus, whenever there's mention of a returned value, it's about that
# intended value.
# Helper function to implement conditional value variants, with a default
# plus additional values based on the value of $config{build_type}.
# Arguments are given in hash table form:
#
# picker(default => "Basic string: ",
# debug => "debug",
# release => "release")
#
# When configuring with --debug, the resulting string will be
# "Basic string: debug", and when not, it will be "Basic string: release"
#
# This can be used to create variants of sets of flags according to the
# build type:
#
# cflags => picker(default => "-Wall",
# debug => "-g -O0",
# release => "-O3")
#
sub picker {
my %opts = @_;
return sub { add($opts{default} || (),
$opts{$config{build_type}} || ())->(); }
}
# Helper function to combine several values of different types into one.
# This is useful if you want to combine a string with the result of a
# lazy function, such as:
#
# cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" })
#
sub combine {
my @stuff = @_;
return sub { add(@stuff)->(); }
}
# Helper function to implement conditional values depending on the value
# of $disabled{threads}. Can be used as follows:
#
# cflags => combine("-Wall", threads("-pthread"))
#
sub threads {
my @flags = @_;
return sub { add($disabled{threads} ? () : @flags)->(); }
}
sub shared {
my @flags = @_;
return sub { add($disabled{shared} ? () : @flags)->(); }
}
our $add_called = 0;
# Helper function to implement adding values to already existing configuration
# values. It handles elements that are ARRAYs, CODEs and scalars
sub _add {
my $separator = shift;
# If there's any ARRAY in the collection of values OR the separator
# is undef, we will return an ARRAY of combined values, otherwise a
# string of joined values with $separator as the separator.
my $found_array = !defined($separator);
my @values =
map {
my $res = $_;
while (ref($res) eq "CODE") {
$res = $res->();
}
if (defined($res)) {
if (ref($res) eq "ARRAY") {
$found_array = 1;
@$res;
} else {
$res;
}
} else {
();
}
} (@_);
$add_called = 1;
if ($found_array) {
[ @values ];
} else {
join($separator, grep { defined($_) && $_ ne "" } @values);
}
}
sub add_before {
my $separator = " ";
if (ref($_[$#_]) eq "HASH") {
my $opts = pop;
$separator = $opts->{separator};
}
my @x = @_;
sub { _add($separator, @x, @_) };
}
sub add {
my $separator = " ";
if (ref($_[$#_]) eq "HASH") {
my $opts = pop;
$separator = $opts->{separator};
}
my @x = @_;
sub { _add($separator, @_, @x) };
}
sub read_eval_file {
my $fname = shift;
my $content;
my @result;
open F, "< $fname" or die "Can't open '$fname': $!\n";
{
undef local $/;
$content = <F>;
}
close F;
{
local $@;
@result = ( eval $content );
warn $@ if $@;
}
return wantarray ? @result : $result[0];
}
# configuration reader, evaluates the input file as a perl script and expects
# it to fill %targets with target configurations. Those are then added to
# %table.
sub read_config {
my $fname = shift;
my %targets;
{
# Protect certain tables from tampering
local %table = ();
%targets = read_eval_file($fname);
}
my %preexisting = ();
foreach (sort keys %targets) {
$preexisting{$_} = 1 if $table{$_};
}
die <<"EOF",
The following config targets from $fname
shadow pre-existing config targets with the same name:
EOF
map { " $_\n" } sort keys %preexisting
if %preexisting;
# For each target, check that it's configured with a hash table.
foreach (keys %targets) {
if (ref($targets{$_}) ne "HASH") {
if (ref($targets{$_}) eq "") {
warn "Deprecated target configuration for $_, ignoring...\n";
} else {
warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
}
delete $targets{$_};
} else {
$targets{$_}->{_conf_fname_int} = add([ $fname ]);
}
}
%table = (%table, %targets);
}
# configuration resolver. Will only resolve all the lazy evaluation
# codeblocks for the chosen target and all those it inherits from,
# recursively
sub resolve_config {
my $target = shift;
my @breadcrumbs = @_;
# my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS});
if (grep { $_ eq $target } @breadcrumbs) {
die "inherit_from loop! target backtrace:\n "
,$target,"\n ",join("\n ", @breadcrumbs),"\n";
}
if (!defined($table{$target})) {
warn "Warning! target $target doesn't exist!\n";
return ();
}
# Recurse through all inheritances. They will be resolved on the
# fly, so when this operation is done, they will all just be a
# bunch of attributes with string values.
# What we get here, though, are keys with references to lists of
# the combined values of them all. We will deal with lists after
# this stage is done.
my %combined_inheritance = ();
if ($table{$target}->{inherit_from}) {
my @inherit_from =
map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
foreach (@inherit_from) {
my %inherited_config = resolve_config($_, $target, @breadcrumbs);
# 'template' is a marker that's considered private to
# the config that had it.
delete $inherited_config{template};
foreach (keys %inherited_config) {
if (!$combined_inheritance{$_}) {
$combined_inheritance{$_} = [];
}
push @{$combined_inheritance{$_}}, $inherited_config{$_};
}
}
}
# We won't need inherit_from in this target any more, since we've
# resolved all the inheritances that lead to this
delete $table{$target}->{inherit_from};
# Now is the time to deal with those lists. Here's the place to
# decide what shall be done with those lists, all based on the
# values of the target we're currently dealing with.
# - If a value is a coderef, it will be executed with the list of
# inherited values as arguments.
# - If the corresponding key doesn't have a value at all or is the
# empty string, the inherited value list will be run through the
# default combiner (below), and the result becomes this target's
# value.
# - Otherwise, this target's value is assumed to be a string that
# will simply override the inherited list of values.
my $default_combiner = add();
my %all_keys =
map { $_ => 1 } (keys %combined_inheritance,
keys %{$table{$target}});
sub process_values {
my $object = shift;
my $inherited = shift; # Always a [ list ]
my $target = shift;
my $entry = shift;
$add_called = 0;
while(ref($object) eq "CODE") {
$object = $object->(@$inherited);
}
if (!defined($object)) {
return ();
}
elsif (ref($object) eq "ARRAY") {
local $add_called; # To make sure recursive calls don't affect it
return [ map { process_values($_, $inherited, $target, $entry) }
@$object ];
} elsif (ref($object) eq "") {
return $object;
} else {
die "cannot handle reference type ",ref($object)
," found in target ",$target," -> ",$entry,"\n";
}
}
foreach my $key (sort keys %all_keys) {
my $previous = $combined_inheritance{$key};
# Current target doesn't have a value for the current key?
# Assign it the default combiner, the rest of this loop body
# will handle it just like any other coderef.
if (!exists $table{$target}->{$key}) {
$table{$target}->{$key} = $default_combiner;
}
$table{$target}->{$key} = process_values($table{$target}->{$key},
$combined_inheritance{$key},
$target, $key);
unless(defined($table{$target}->{$key})) {
delete $table{$target}->{$key};
}
# if ($extra_checks &&
# $previous && !($add_called || $previous ~~ $table{$target}->{$key})) {
# warn "$key got replaced in $target\n";
# }
}
# Finally done, return the result.
return %{$table{$target}};
}
sub usage
{
print STDERR $usage;
print STDERR "\npick os/compiler from:\n";
my $j=0;
my $i;
my $k=0;
foreach $i (sort keys %table)
{
next if $table{$i}->{template};
next if $i =~ /^debug/;
$k += length($i) + 1;
if ($k > 78)
{
print STDERR "\n";
$k=length($i);
}
print STDERR $i . " ";
}
foreach $i (sort keys %table)
{
next if $table{$i}->{template};
next if $i !~ /^debug/;
$k += length($i) + 1;
if ($k > 78)
{
print STDERR "\n";
$k=length($i);
}
print STDERR $i . " ";
}
exit(1);
}
sub compiler_predefined {
state %predefined;
my $cc = shift;
return () if $^O eq 'VMS';
die 'compiler_predefined called without a compiler command'
unless $cc;
if (! $predefined{$cc}) {
$predefined{$cc} = {};
# collect compiler pre-defines from gcc or gcc-alike...
open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
while (my $l = <PIPE>) {
$l =~ m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
$predefined{$cc}->{$1} = $2 // '';
}
close(PIPE);
}
return %{$predefined{$cc}};
}
sub which
{
my ($name)=@_;
if (eval { require IPC::Cmd; 1; }) {
IPC::Cmd->import();
return scalar IPC::Cmd::can_run($name);
} else {
# if there is $directories component in splitpath,
# then it's not something to test with $PATH...
return $name if (File::Spec->splitpath($name))[1];
foreach (File::Spec->path()) {
my $fullpath = catfile($_, "$name$target{exe_extension}");
if (-f $fullpath and -x $fullpath) {
return $fullpath;
}
}
}
}
sub env
{
my $name = shift;
my %opts = @_;
unless ($opts{cacheonly}) {
# Note that if $ENV{$name} doesn't exist or is undefined,
# $config{perlenv}->{$name} will be created with the value
# undef. This is intentional.
$config{perlenv}->{$name} = $ENV{$name}
if ! exists $config{perlenv}->{$name};
}
return $config{perlenv}->{$name};
}
# Configuration printer ##############################################
sub print_table_entry
{
local $now_printing = shift;
my %target = resolve_config($now_printing);
my $type = shift;
# Don't print the templates
return if $target{template};
my @sequence = (
"sys_id",
"cpp",
"cppflags",
"defines",
"includes",
"cc",
"cflags",
"ld",
"lflags",
"loutflag",
"ex_libs",
"bn_ops",
"enable",
"disable",
"poly1035_asm_src",
"thread_scheme",
"perlasm_scheme",
"dso_scheme",
"shared_target",
"shared_cflag",
"shared_defines",
"shared_ldflag",
"shared_rcflag",
"shared_extension",
"dso_extension",
"obj_extension",
"exe_extension",
"ranlib",
"ar",
"arflags",
"aroutflag",
"rc",
"rcflags",
"rcoutflag",
"mt",
"mtflags",
"mtinflag",
"mtoutflag",
"multilib",
"build_scheme",
);
if ($type eq "TABLE") {
print "\n";
print "*** $now_printing\n";
foreach (@sequence) {
if (ref($target{$_}) eq "ARRAY") {
printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}});
} else {
printf "\$%-12s = %s\n", $_, $target{$_};
}
}
} elsif ($type eq "HASH") {
my $largest =
length((sort { length($a) <=> length($b) } @sequence)[-1]);
print " '$now_printing' => {\n";
foreach (@sequence) {
if ($target{$_}) {
if (ref($target{$_}) eq "ARRAY") {
print " '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
} else {
print " '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n";
}
}
}
print " },\n";
}
}
# Utility routines ###################################################
# On VMS, if the given file is a logical name, File::Spec::Functions
# will consider it an absolute path. There are cases when we want a
# purely syntactic check without checking the environment.
sub isabsolute {
my $file = shift;
# On non-platforms, we just use file_name_is_absolute().
return file_name_is_absolute($file) unless $^O eq "VMS";
# If the file spec includes a device or a directory spec,
# file_name_is_absolute() is perfectly safe.
return file_name_is_absolute($file) if $file =~ m|[:\[]|;
# Here, we know the given file spec isn't absolute
return 0;
}
# Makes a directory absolute and cleans out /../ in paths like foo/../bar
# On some platforms, this uses rel2abs(), while on others, realpath() is used.
# realpath() requires that at least all path components except the last is an
# existing directory. On VMS, the last component of the directory spec must
# exist.
sub absolutedir {
my $dir = shift;
# realpath() is quite buggy on VMS. It uses LIB$FID_TO_NAME, which
# will return the volume name for the device, no matter what. Also,
# it will return an incorrect directory spec if the argument is a
# directory that doesn't exist.
if ($^O eq "VMS") {
return rel2abs($dir);
}
# We use realpath() on Unix, since no other will properly clean out
# a directory spec.
use Cwd qw/realpath/;
return realpath($dir);
}
# Check if all paths are one and the same, using stat. They must both exist
# We need this for the cases when File::Spec doesn't detect case insensitivity
# (File::Spec::Unix assumes case sensitivity)
sub samedir {
die "samedir expects two arguments\n" unless scalar @_ == 2;
my @stat0 = stat($_[0]); # First argument
my @stat1 = stat($_[1]); # Second argument
die "Couldn't stat $_[0]" unless @stat0;
die "Couldn't stat $_[1]" unless @stat1;
# Compare device number
return 0 unless ($stat0[0] == $stat1[0]);
# Compare "inode". The perl manual recommends comparing as
# string rather than as number.
return 0 unless ($stat0[1] eq $stat1[1]);
return 1; # All the same
}
sub quotify {
my %processors = (
perl => sub { my $x = shift;
$x =~ s/([\\\$\@"])/\\$1/g;
return '"'.$x.'"'; },
maybeshell => sub { my $x = shift;
(my $y = $x) =~ s/([\\\"])/\\$1/g;
if ($x ne $y || $x =~ m|\s|) {
return '"'.$y.'"';
} else {
return $x;
}
},
);
my $for = shift;
my $processor =
defined($processors{$for}) ? $processors{$for} : sub { shift; };
return map { $processor->($_); } @_;
}
# collect_from_file($filename, $line_concat_cond_re, $line_concat)
# $filename is a file name to read from
# $line_concat_cond_re is a regexp detecting a line continuation ending
# $line_concat is a CODEref that takes care of concatenating two lines
sub collect_from_file {
my $filename = shift;
my $line_concat_cond_re = shift;
my $line_concat = shift;
open my $fh, $filename || die "unable to read $filename: $!\n";
return sub {
my $saved_line = "";
$_ = "";
while (<$fh>) {
s|\R$||;
if (defined $line_concat) {
$_ = $line_concat->($saved_line, $_);
$saved_line = "";
}
if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
$saved_line = $_;
next;
}
return $_;
}
die "$filename ending with continuation line\n" if $_;
close $fh;
return undef;
}
}
# collect_from_array($array, $line_concat_cond_re, $line_concat)
# $array is an ARRAYref of lines
# $line_concat_cond_re is a regexp detecting a line continuation ending
# $line_concat is a CODEref that takes care of concatenating two lines
sub collect_from_array {
my $array = shift;
my $line_concat_cond_re = shift;
my $line_concat = shift;
my @array = (@$array);
return sub {
my $saved_line = "";
$_ = "";
while (defined($_ = shift @array)) {
s|\R$||;
if (defined $line_concat) {
$_ = $line_concat->($saved_line, $_);
$saved_line = "";
}
if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
$saved_line = $_;
next;
}
return $_;
}
die "input text ending with continuation line\n" if $_;
return undef;
}
}
# collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
# $lineiterator is a CODEref that delivers one line at a time.
# All following arguments are regex/CODEref pairs, where the regexp detects a
# line and the CODEref does something with the result of the regexp.
sub collect_information {
my $lineiterator = shift;
my %collectors = @_;
while(defined($_ = $lineiterator->())) {
s|\R$||;
my $found = 0;
if ($collectors{"BEFORE"}) {
$collectors{"BEFORE"}->($_);
}
foreach my $re (keys %collectors) {
if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) {
$collectors{$re}->($lineiterator);
$found = 1;
};
}
if ($collectors{"OTHERWISE"}) {
$collectors{"OTHERWISE"}->($lineiterator, $_)
unless $found || !defined $collectors{"OTHERWISE"};
}
if ($collectors{"AFTER"}) {
$collectors{"AFTER"}->($_);
}
}
}
# tokenize($line)
# tokenize($line,$separator)
# $line is a line of text to split up into tokens
# $separator [optional] is a regular expression that separates the tokens,
# the default being spaces. Do not use quotes of any kind as separators,
# that will give undefined results.
# Returns a list of tokens.
#
# Tokens are divided by separator (spaces by default). If the tokens include
# the separators, they have to be quoted with single or double quotes.
# Double quotes inside a double quoted token must be escaped. Escaping is done
# with backslash.
# Basically, the same quoting rules apply for " and ' as in any
# Unix shell.
sub tokenize {
my $line = my $debug_line = shift;
my $separator = shift // qr|\s+|;
my @result = ();
if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
print STDERR "DEBUG[tokenize]: \$separator = $separator\n";
}
while ($line =~ s|^${separator}||, $line ne "") {
my $token = "";
again:
$line =~ m/^(.*?)(${separator}|"|'|$)/;
$token .= $1;
$line = $2.$';
if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
$token .= $1;
$line = $';
goto again;
} elsif ($line =~ m/^'([^']*)'/) {
$token .= $1;
$line = $';
goto again;
}
push @result, $token;
}
if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n";
print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n";
}
return @result;
}
diff --git a/NEWS.md b/NEWS.md
index 36dbfa72f6d5..10fbf5c9481c 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,1586 +1,1603 @@
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.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-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-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/NOTES-NONSTOP.md b/NOTES-NONSTOP.md
index 627843babf32..68438b998884 100644
--- a/NOTES-NONSTOP.md
+++ b/NOTES-NONSTOP.md
@@ -1,245 +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.
+
+A resolution to this situation is under investigation.
+
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:
./Configure nonstop-nsx_64 no-makedepend --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/NOTES-VMS.md b/NOTES-VMS.md
index e27f3d682a2a..566a04d2a9fe 100644
--- a/NOTES-VMS.md
+++ b/NOTES-VMS.md
@@ -1,115 +1,132 @@
Notes for the OpenVMS platform
==============================
- [Requirement details](#requirement-details)
- [About ANSI C compiler](#about-ansi-c-compiler)
- [About ODS-5 directory names and Perl](#about-ods-5-directory-names-and-perl)
- [About MMS and DCL](#about-mms-and-dcl)
- [About debugging](#about-debugging)
- [Checking the distribution](#checking-the-distribution)
Requirement details
-------------------
In addition to the requirements and instructions listed
in [INSTALL.md](INSTALL.md), this are required as well:
* At least ODS-5 disk organization for source and build.
Installation can be done on any existing disk organization.
About ANSI C compiler
---------------------
An ANSI C compiled is needed among other things. This means that
VAX C is not and will not be supported.
We have only tested with DEC C (aka HP VMS C / VSI C) and require
version 7.1 or later. Compiling with a different ANSI C compiler may
require some work.
Please avoid using C RTL feature logical names `DECC$*` when building
and testing OpenSSL. Most of all, they can be disruptive when
running the tests, as they affect the Perl interpreter.
About ODS-5 directory names and Perl
------------------------------------
It seems that the perl function canonpath() in the `File::Spec` module
doesn't treat file specifications where the last directory name
contains periods very well. Unfortunately, some versions of VMS tar
will keep the periods in the OpenSSL source directory instead of
converting them to underscore, thereby leaving your source in
something like `[.openssl-1^.1^.0]`. This will lead to issues when
configuring and building OpenSSL.
We have no replacement for Perl's canonpath(), so the best workaround
for now is to rename the OpenSSL source directory, as follows (please
adjust for the actual source directory name you have):
$ rename openssl-1^.1^.0.DIR openssl-1_1_0.DIR
About MMS and DCL
-----------------
MMS has certain limitations when it comes to line length, and DCL has
certain limitations when it comes to total command length. We do
what we can to mitigate, but there is the possibility that it's not
enough. Should you run into issues, a very simple solution is to set
yourself up a few logical names for the directory trees you're going
to use.
About debugging
---------------
If you build for debugging, the default on VMS is that image
activation starts the debugger automatically, giving you a debug
prompt. Unfortunately, this disrupts all other uses, such as running
test programs in the test framework.
Generally speaking, if you build for debugging, only use the programs
directly for debugging. Do not try to use them from a script, such
as running the test suite.
### The following is not available on Alpha
As a compromise, we're turning off the flag that makes the debugger
start automatically. If there is a program that you need to debug,
you need to turn that flag back on first, for example:
$ set image /flag=call_debug [.test]evp_test.exe
Then just run it and you will find yourself in a debugging session.
When done, we recommend that you turn that flag back off:
$ set image /flag=nocall_debug [.test]evp_test.exe
+About assembler acceleration
+----------------------------
+
+OpenSSL has assembler acceleration for a number of BIGNUM and crypto
+routines. The VMS config targets tries to look for a selection of
+assemblers and will use what they find. If none of the assemblers are
+found, OpenSSL will be built as if `no-asm` was configured.
+
+### For Itanium / IA64 / I64
+
+- There is only one assembler, a port of Intel's `ias`, found in the
+ HP Open Source Tools CD, available through [DECUSlib](http://www.decuslib.com).
+ It's assumed to be set up as per the instructions, where `disk` and
+ `dir` are expected to be adapted to local conditions:
+
+ $ ias :== $disk:[dir]iasi64.exe
+
Checking the distribution
-------------------------
There have been reports of places where the distribution didn't quite
get through, for example if you've copied the tree from a NFS-mounted
Unix mount point.
The easiest way to check if everything got through as it should is to
check that this file exists:
[.include.openssl]configuration^.h.in
The best way to get a correct distribution is to download the gzipped
tar file from ftp://ftp.openssl.org/source/, use `GZIP -d` to uncompress
it and `VMSTAR` to unpack the resulting tar file.
Gzip and VMSTAR are available here:
<http://antinode.info/dec/index.html#Software>
Should you need it, you can find UnZip for VMS here:
<http://www.info-zip.org/UnZip.html>
How the value of 'arch' is determined
-------------------------------------
'arch' is mentioned in INSTALL. It's value is determined like this:
arch = f$edit( f$getsyi( "arch_name"), "upcase")
diff --git a/VERSION.dat b/VERSION.dat
index 375a0de7e128..be1c292b2ad7 100644
--- a/VERSION.dat
+++ b/VERSION.dat
@@ -1,7 +1,7 @@
MAJOR=3
MINOR=0
-PATCH=8
+PATCH=9
PRE_RELEASE_TAG=
BUILD_METADATA=
-RELEASE_DATE="7 Feb 2023"
+RELEASE_DATE="30 May 2023"
SHLIB_VERSION=3
diff --git a/apps/cmp.c b/apps/cmp.c
index 9b9e405bb248..3463579c24fb 100644
--- a/apps/cmp.c
+++ b/apps/cmp.c
@@ -1,3023 +1,3083 @@
/*
- * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/* This app is disabled when OPENSSL_NO_CMP is defined. */
#include <string.h>
#include <ctype.h>
#include "apps.h"
#include "http_server.h"
#include "s_apps.h"
#include "progs.h"
#include "cmp_mock_srv.h"
/* tweaks needed due to missing unistd.h on Windows */
#if defined(_WIN32) && !defined(__BORLANDC__)
# define access _access
#endif
#ifndef F_OK
# define F_OK 0
#endif
#include <openssl/ui.h>
#include <openssl/pkcs12.h>
#include <openssl/ssl.h>
/* explicit #includes not strictly needed since implied by the above: */
#include <stdlib.h>
#include <openssl/cmp.h>
#include <openssl/cmp_util.h>
#include <openssl/crmf.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/store.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
static char *prog;
static char *opt_config = NULL;
#define CMP_SECTION "cmp"
#define SECTION_NAME_MAX 40 /* max length of section name */
#define DEFAULT_SECTION "default"
static char *opt_section = CMP_SECTION;
static int opt_verbosity = OSSL_CMP_LOG_INFO;
static int read_config(void);
static CONF *conf = NULL; /* OpenSSL config file context structure */
static OSSL_CMP_CTX *cmp_ctx = NULL; /* the client-side CMP context */
/* the type of cmp command we want to send */
typedef enum {
CMP_IR,
CMP_KUR,
CMP_CR,
CMP_P10CR,
CMP_RR,
CMP_GENM
} cmp_cmd_t;
/* message transfer */
#ifndef OPENSSL_NO_SOCK
static char *opt_server = NULL;
static char *opt_proxy = NULL;
static char *opt_no_proxy = NULL;
#endif
static char *opt_recipient = NULL;
static char *opt_path = NULL;
static int opt_keep_alive = 1;
static int opt_msg_timeout = -1;
static int opt_total_timeout = -1;
/* server authentication */
static char *opt_trusted = NULL;
static char *opt_untrusted = NULL;
static char *opt_srvcert = NULL;
static char *opt_expect_sender = NULL;
static int opt_ignore_keyusage = 0;
static int opt_unprotected_errors = 0;
static char *opt_extracertsout = NULL;
static char *opt_cacertsout = NULL;
/* client authentication */
static char *opt_ref = NULL;
static char *opt_secret = NULL;
static char *opt_cert = NULL;
static char *opt_own_trusted = NULL;
static char *opt_key = NULL;
static char *opt_keypass = NULL;
static char *opt_digest = NULL;
static char *opt_mac = NULL;
static char *opt_extracerts = NULL;
static int opt_unprotected_requests = 0;
/* generic message */
static char *opt_cmd_s = NULL;
static int opt_cmd = -1;
static char *opt_geninfo = NULL;
static char *opt_infotype_s = NULL;
static int opt_infotype = NID_undef;
/* certificate enrollment */
static char *opt_newkey = NULL;
static char *opt_newkeypass = NULL;
static char *opt_subject = NULL;
static char *opt_issuer = NULL;
static int opt_days = 0;
static char *opt_reqexts = NULL;
static char *opt_sans = NULL;
static int opt_san_nodefault = 0;
static char *opt_policies = NULL;
static char *opt_policy_oids = NULL;
static int opt_policy_oids_critical = 0;
static int opt_popo = OSSL_CRMF_POPO_NONE - 1;
static char *opt_csr = NULL;
static char *opt_out_trusted = NULL;
static int opt_implicit_confirm = 0;
static int opt_disable_confirm = 0;
static char *opt_certout = NULL;
static char *opt_chainout = NULL;
/* certificate enrollment and revocation */
static char *opt_oldcert = NULL;
static int opt_revreason = CRL_REASON_NONE;
/* credentials format */
static char *opt_certform_s = "PEM";
static int opt_certform = FORMAT_PEM;
static char *opt_keyform_s = NULL;
static int opt_keyform = FORMAT_UNDEF;
static char *opt_otherpass = NULL;
static char *opt_engine = NULL;
#ifndef OPENSSL_NO_SOCK
/* TLS connection */
static int opt_tls_used = 0;
static char *opt_tls_cert = NULL;
static char *opt_tls_key = NULL;
static char *opt_tls_keypass = NULL;
static char *opt_tls_extra = NULL;
static char *opt_tls_trusted = NULL;
static char *opt_tls_host = NULL;
#endif
/* client-side debugging */
static int opt_batch = 0;
static int opt_repeat = 1;
static char *opt_reqin = NULL;
static int opt_reqin_new_tid = 0;
static char *opt_reqout = NULL;
static char *opt_rspin = NULL;
+static int rspin_in_use = 0;
static char *opt_rspout = NULL;
static int opt_use_mock_srv = 0;
/* mock server */
#ifndef OPENSSL_NO_SOCK
static char *opt_port = NULL;
static int opt_max_msgs = 0;
#endif
static char *opt_srv_ref = NULL;
static char *opt_srv_secret = NULL;
static char *opt_srv_cert = NULL;
static char *opt_srv_key = NULL;
static char *opt_srv_keypass = NULL;
static char *opt_srv_trusted = NULL;
static char *opt_srv_untrusted = NULL;
static char *opt_rsp_cert = NULL;
static char *opt_rsp_extracerts = NULL;
static char *opt_rsp_capubs = NULL;
static int opt_poll_count = 0;
static int opt_check_after = 1;
static int opt_grant_implicitconf = 0;
static int opt_pkistatus = OSSL_CMP_PKISTATUS_accepted;
static int opt_failure = INT_MIN;
static int opt_failurebits = 0;
static char *opt_statusstring = NULL;
static int opt_send_error = 0;
static int opt_send_unprotected = 0;
static int opt_send_unprot_err = 0;
static int opt_accept_unprotected = 0;
static int opt_accept_unprot_err = 0;
static int opt_accept_raverified = 0;
static X509_VERIFY_PARAM *vpm = NULL;
typedef enum OPTION_choice {
OPT_COMMON,
OPT_CONFIG, OPT_SECTION, OPT_VERBOSITY,
OPT_CMD, OPT_INFOTYPE, OPT_GENINFO,
OPT_NEWKEY, OPT_NEWKEYPASS, OPT_SUBJECT, OPT_ISSUER,
OPT_DAYS, OPT_REQEXTS,
OPT_SANS, OPT_SAN_NODEFAULT,
OPT_POLICIES, OPT_POLICY_OIDS, OPT_POLICY_OIDS_CRITICAL,
OPT_POPO, OPT_CSR,
OPT_OUT_TRUSTED, OPT_IMPLICIT_CONFIRM, OPT_DISABLE_CONFIRM,
OPT_CERTOUT, OPT_CHAINOUT,
OPT_OLDCERT, OPT_REVREASON,
#ifndef OPENSSL_NO_SOCK
OPT_SERVER, OPT_PROXY, OPT_NO_PROXY,
#endif
OPT_RECIPIENT, OPT_PATH,
OPT_KEEP_ALIVE, OPT_MSG_TIMEOUT, OPT_TOTAL_TIMEOUT,
OPT_TRUSTED, OPT_UNTRUSTED, OPT_SRVCERT,
OPT_EXPECT_SENDER,
OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS,
OPT_EXTRACERTSOUT, OPT_CACERTSOUT,
OPT_REF, OPT_SECRET, OPT_CERT, OPT_OWN_TRUSTED, OPT_KEY, OPT_KEYPASS,
OPT_DIGEST, OPT_MAC, OPT_EXTRACERTS,
OPT_UNPROTECTED_REQUESTS,
OPT_CERTFORM, OPT_KEYFORM,
OPT_OTHERPASS,
#ifndef OPENSSL_NO_ENGINE
OPT_ENGINE,
#endif
OPT_PROV_ENUM,
OPT_R_ENUM,
#ifndef OPENSSL_NO_SOCK
OPT_TLS_USED, OPT_TLS_CERT, OPT_TLS_KEY,
OPT_TLS_KEYPASS,
OPT_TLS_EXTRA, OPT_TLS_TRUSTED, OPT_TLS_HOST,
#endif
OPT_BATCH, OPT_REPEAT,
OPT_REQIN, OPT_REQIN_NEW_TID, OPT_REQOUT, OPT_RSPIN, OPT_RSPOUT,
OPT_USE_MOCK_SRV,
#ifndef OPENSSL_NO_SOCK
OPT_PORT, OPT_MAX_MSGS,
#endif
OPT_SRV_REF, OPT_SRV_SECRET,
OPT_SRV_CERT, OPT_SRV_KEY, OPT_SRV_KEYPASS,
OPT_SRV_TRUSTED, OPT_SRV_UNTRUSTED,
OPT_RSP_CERT, OPT_RSP_EXTRACERTS, OPT_RSP_CAPUBS,
OPT_POLL_COUNT, OPT_CHECK_AFTER,
OPT_GRANT_IMPLICITCONF,
OPT_PKISTATUS, OPT_FAILURE,
OPT_FAILUREBITS, OPT_STATUSSTRING,
OPT_SEND_ERROR, OPT_SEND_UNPROTECTED,
OPT_SEND_UNPROT_ERR, OPT_ACCEPT_UNPROTECTED,
OPT_ACCEPT_UNPROT_ERR, OPT_ACCEPT_RAVERIFIED,
OPT_V_ENUM
} OPTION_CHOICE;
const OPTIONS cmp_options[] = {
/* entries must be in the same order as enumerated above!! */
{"help", OPT_HELP, '-', "Display this summary"},
{"config", OPT_CONFIG, 's',
"Configuration file to use. \"\" = none. Default from env variable OPENSSL_CONF"},
{"section", OPT_SECTION, 's',
"Section(s) in config file to get options from. \"\" = 'default'. Default 'cmp'"},
{"verbosity", OPT_VERBOSITY, 'N',
"Log level; 3=ERR, 4=WARN, 6=INFO, 7=DEBUG, 8=TRACE. Default 6 = INFO"},
OPT_SECTION("Generic message"),
{"cmd", OPT_CMD, 's', "CMP request to send: ir/cr/kur/p10cr/rr/genm"},
{"infotype", OPT_INFOTYPE, 's',
"InfoType name for requesting specific info in genm, e.g. 'signKeyPairTypes'"},
{"geninfo", OPT_GENINFO, 's',
"generalInfo integer values to place in request PKIHeader with given OID"},
{OPT_MORE_STR, 0, 0,
"specified in the form <OID>:int:<n>, e.g. \"1.2.3.4:int:56789\""},
OPT_SECTION("Certificate enrollment"),
{"newkey", OPT_NEWKEY, 's',
"Private or public key for the requested cert. Default: CSR key or client key"},
{"newkeypass", OPT_NEWKEYPASS, 's', "New private key pass phrase source"},
{"subject", OPT_SUBJECT, 's',
"Distinguished Name (DN) of subject to use in the requested cert template"},
{OPT_MORE_STR, 0, 0,
"For kur, default is subject of -csr arg or reference cert (see -oldcert)"},
{OPT_MORE_STR, 0, 0,
"this default is used for ir and cr only if no Subject Alt Names are set"},
{"issuer", OPT_ISSUER, 's',
"DN of the issuer to place in the requested certificate template"},
{OPT_MORE_STR, 0, 0,
"also used as recipient if neither -recipient nor -srvcert are given"},
{"days", OPT_DAYS, 'N',
"Requested validity time of the new certificate in number of days"},
{"reqexts", OPT_REQEXTS, 's',
"Name of config file section defining certificate request extensions."},
{OPT_MORE_STR, 0, 0,
"Augments or replaces any extensions contained CSR given with -csr"},
{"sans", OPT_SANS, 's',
"Subject Alt Names (IPADDR/DNS/URI) to add as (critical) cert req extension"},
{"san_nodefault", OPT_SAN_NODEFAULT, '-',
"Do not take default SANs from reference certificate (see -oldcert)"},
{"policies", OPT_POLICIES, 's',
"Name of config file section defining policies certificate request extension"},
{"policy_oids", OPT_POLICY_OIDS, 's',
"Policy OID(s) to add as policies certificate request extension"},
{"policy_oids_critical", OPT_POLICY_OIDS_CRITICAL, '-',
"Flag the policy OID(s) given with -policy_oids as critical"},
{"popo", OPT_POPO, 'n',
"Proof-of-Possession (POPO) method to use for ir/cr/kur where"},
{OPT_MORE_STR, 0, 0,
"-1 = NONE, 0 = RAVERIFIED, 1 = SIGNATURE (default), 2 = KEYENC"},
{"csr", OPT_CSR, 's',
"PKCS#10 CSR file in PEM or DER format to convert or to use in p10cr"},
{"out_trusted", OPT_OUT_TRUSTED, 's',
"Certificates to trust when verifying newly enrolled certificates"},
{"implicit_confirm", OPT_IMPLICIT_CONFIRM, '-',
"Request implicit confirmation of newly enrolled certificates"},
{"disable_confirm", OPT_DISABLE_CONFIRM, '-',
"Do not confirm newly enrolled certificate w/o requesting implicit"},
{OPT_MORE_STR, 0, 0,
"confirmation. WARNING: This leads to behavior violating RFC 4210"},
{"certout", OPT_CERTOUT, 's',
"File to save newly enrolled certificate"},
{"chainout", OPT_CHAINOUT, 's',
"File to save the chain of newly enrolled certificate"},
OPT_SECTION("Certificate enrollment and revocation"),
{"oldcert", OPT_OLDCERT, 's',
"Certificate to be updated (defaulting to -cert) or to be revoked in rr;"},
{OPT_MORE_STR, 0, 0,
"also used as reference (defaulting to -cert) for subject DN and SANs."},
{OPT_MORE_STR, 0, 0,
"Issuer is used as recipient unless -recipient, -srvcert, or -issuer given"},
{"revreason", OPT_REVREASON, 'n',
"Reason code to include in revocation request (rr); possible values:"},
{OPT_MORE_STR, 0, 0,
"0..6, 8..10 (see RFC5280, 5.3.1) or -1. Default -1 = none included"},
OPT_SECTION("Message transfer"),
#ifdef OPENSSL_NO_SOCK
{OPT_MORE_STR, 0, 0,
"NOTE: -server, -proxy, and -no_proxy not supported due to no-sock build"},
#else
{"server", OPT_SERVER, 's',
"[http[s]://]address[:port][/path] of CMP server. Default port 80 or 443."},
{OPT_MORE_STR, 0, 0,
"address may be a DNS name or an IP address; path can be overridden by -path"},
{"proxy", OPT_PROXY, 's',
"[http[s]://]address[:port][/path] of HTTP(S) proxy to use; path is ignored"},
{"no_proxy", OPT_NO_PROXY, 's',
"List of addresses of servers not to use HTTP(S) proxy for"},
{OPT_MORE_STR, 0, 0,
"Default from environment variable 'no_proxy', else 'NO_PROXY', else none"},
#endif
{"recipient", OPT_RECIPIENT, 's',
"DN of CA. Default: subject of -srvcert, -issuer, issuer of -oldcert or -cert"},
{"path", OPT_PATH, 's',
"HTTP path (aka CMP alias) at the CMP server. Default from -server, else \"/\""},
{"keep_alive", OPT_KEEP_ALIVE, 'N',
"Persistent HTTP connections. 0: no, 1 (the default): request, 2: require"},
{"msg_timeout", OPT_MSG_TIMEOUT, 'N',
"Number of seconds allowed per CMP message round trip, or 0 for infinite"},
{"total_timeout", OPT_TOTAL_TIMEOUT, 'N',
"Overall time an enrollment incl. polling may take. Default 0 = infinite"},
OPT_SECTION("Server authentication"),
{"trusted", OPT_TRUSTED, 's',
- "Certificates to trust as chain roots when verifying signed CMP responses"},
+ "Certificates to use as trust anchors when verifying signed CMP responses"},
{OPT_MORE_STR, 0, 0, "unless -srvcert is given"},
{"untrusted", OPT_UNTRUSTED, 's',
"Intermediate CA certs for chain construction for CMP/TLS/enrolled certs"},
{"srvcert", OPT_SRVCERT, 's',
"Server cert to pin and trust directly when verifying signed CMP responses"},
{"expect_sender", OPT_EXPECT_SENDER, 's',
"DN of expected sender of responses. Defaults to subject of -srvcert, if any"},
{"ignore_keyusage", OPT_IGNORE_KEYUSAGE, '-',
"Ignore CMP signer cert key usage, else 'digitalSignature' must be allowed"},
{"unprotected_errors", OPT_UNPROTECTED_ERRORS, '-',
"Accept missing or invalid protection of regular error messages and negative"},
{OPT_MORE_STR, 0, 0,
"certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf"},
{OPT_MORE_STR, 0, 0,
"WARNING: This setting leads to behavior allowing violation of RFC 4210"},
{"extracertsout", OPT_EXTRACERTSOUT, 's',
"File to save extra certificates received in the extraCerts field"},
{"cacertsout", OPT_CACERTSOUT, 's',
"File to save CA certificates received in the caPubs field of 'ip' messages"},
OPT_SECTION("Client authentication"),
{"ref", OPT_REF, 's',
"Reference value to use as senderKID in case no -cert is given"},
{"secret", OPT_SECRET, 's',
"Prefer PBM (over signatures) for protecting msgs with given password source"},
{"cert", OPT_CERT, 's',
"Client's CMP signer certificate; its public key must match the -key argument"},
{OPT_MORE_STR, 0, 0,
"This also used as default reference for subject DN and SANs."},
{OPT_MORE_STR, 0, 0,
"Any further certs included are appended to the untrusted certs"},
{"own_trusted", OPT_OWN_TRUSTED, 's',
"Optional certs to verify chain building for own CMP signer cert"},
{"key", OPT_KEY, 's', "CMP signer private key, not used when -secret given"},
{"keypass", OPT_KEYPASS, 's',
"Client private key (and cert and old cert) pass phrase source"},
{"digest", OPT_DIGEST, 's',
"Digest to use in message protection and POPO signatures. Default \"sha256\""},
{"mac", OPT_MAC, 's',
"MAC algorithm to use in PBM-based message protection. Default \"hmac-sha1\""},
{"extracerts", OPT_EXTRACERTS, 's',
"Certificates to append in extraCerts field of outgoing messages."},
{OPT_MORE_STR, 0, 0,
"This can be used as the default CMP signer cert chain to include"},
{"unprotected_requests", OPT_UNPROTECTED_REQUESTS, '-',
- "Send messages without CMP-level protection"},
+ "Send request messages without CMP-level protection"},
OPT_SECTION("Credentials format"),
{"certform", OPT_CERTFORM, 's',
"Format (PEM or DER) to use when saving a certificate to a file. Default PEM"},
{"keyform", OPT_KEYFORM, 's',
"Format of the key input (ENGINE, other values ignored)"},
{"otherpass", OPT_OTHERPASS, 's',
"Pass phrase source potentially needed for loading certificates of others"},
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's',
"Use crypto engine with given identifier, possibly a hardware device."},
{OPT_MORE_STR, 0, 0,
"Engines may also be defined in OpenSSL config file engine section."},
#endif
OPT_PROV_OPTIONS,
OPT_R_OPTIONS,
OPT_SECTION("TLS connection"),
#ifdef OPENSSL_NO_SOCK
{OPT_MORE_STR, 0, 0,
"NOTE: -tls_used and all other TLS options not supported due to no-sock build"},
#else
{"tls_used", OPT_TLS_USED, '-',
"Enable using TLS (also when other TLS options are not set)"},
{"tls_cert", OPT_TLS_CERT, 's',
"Client's TLS certificate. May include chain to be provided to TLS server"},
{"tls_key", OPT_TLS_KEY, 's',
"Private key for the client's TLS certificate"},
{"tls_keypass", OPT_TLS_KEYPASS, 's',
"Pass phrase source for the client's private TLS key (and TLS cert)"},
{"tls_extra", OPT_TLS_EXTRA, 's',
"Extra certificates to provide to TLS server during TLS handshake"},
{"tls_trusted", OPT_TLS_TRUSTED, 's',
"Trusted certificates to use for verifying the TLS server certificate;"},
{OPT_MORE_STR, 0, 0, "this implies host name validation"},
{"tls_host", OPT_TLS_HOST, 's',
"Address to be checked (rather than -server) during TLS host name validation"},
#endif
OPT_SECTION("Client-side debugging"),
{"batch", OPT_BATCH, '-',
"Do not interactively prompt for input when a password is required etc."},
{"repeat", OPT_REPEAT, 'p',
"Invoke the transaction the given positive number of times. Default 1"},
- {"reqin", OPT_REQIN, 's', "Take sequence of CMP requests from file(s)"},
+ {"reqin", OPT_REQIN, 's',
+ "Take sequence of CMP requests to send to server from file(s)"},
{"reqin_new_tid", OPT_REQIN_NEW_TID, '-',
"Use fresh transactionID for CMP requests read from -reqin"},
- {"reqout", OPT_REQOUT, 's', "Save sequence of CMP requests to file(s)"},
+ {"reqout", OPT_REQOUT, 's',
+ "Save sequence of CMP requests created by the client to file(s)"},
{"rspin", OPT_RSPIN, 's',
"Process sequence of CMP responses provided in file(s), skipping server"},
- {"rspout", OPT_RSPOUT, 's', "Save sequence of CMP responses to file(s)"},
+ {"rspout", OPT_RSPOUT, 's',
+ "Save sequence of actually used CMP responses to file(s)"},
{"use_mock_srv", OPT_USE_MOCK_SRV, '-',
"Use internal mock server at API level, bypassing socket-based HTTP"},
OPT_SECTION("Mock server"),
#ifdef OPENSSL_NO_SOCK
{OPT_MORE_STR, 0, 0,
"NOTE: -port and -max_msgs not supported due to no-sock build"},
#else
{"port", OPT_PORT, 's',
"Act as HTTP-based mock server listening on given port"},
{"max_msgs", OPT_MAX_MSGS, 'N',
"max number of messages handled by HTTP mock server. Default: 0 = unlimited"},
#endif
{"srv_ref", OPT_SRV_REF, 's',
"Reference value to use as senderKID of server in case no -srv_cert is given"},
{"srv_secret", OPT_SRV_SECRET, 's',
"Password source for server authentication with a pre-shared key (secret)"},
{"srv_cert", OPT_SRV_CERT, 's', "Certificate of the server"},
{"srv_key", OPT_SRV_KEY, 's',
"Private key used by the server for signing messages"},
{"srv_keypass", OPT_SRV_KEYPASS, 's',
"Server private key (and cert) pass phrase source"},
{"srv_trusted", OPT_SRV_TRUSTED, 's',
"Trusted certificates for client authentication"},
{"srv_untrusted", OPT_SRV_UNTRUSTED, 's',
"Intermediate certs that may be useful for verifying CMP protection"},
{"rsp_cert", OPT_RSP_CERT, 's',
"Certificate to be returned as mock enrollment result"},
{"rsp_extracerts", OPT_RSP_EXTRACERTS, 's',
"Extra certificates to be included in mock certification responses"},
{"rsp_capubs", OPT_RSP_CAPUBS, 's',
"CA certificates to be included in mock ip response"},
{"poll_count", OPT_POLL_COUNT, 'N',
"Number of times the client must poll before receiving a certificate"},
{"check_after", OPT_CHECK_AFTER, 'N',
"The check_after value (time to wait) to include in poll response"},
{"grant_implicitconf", OPT_GRANT_IMPLICITCONF, '-',
"Grant implicit confirmation of newly enrolled certificate"},
{"pkistatus", OPT_PKISTATUS, 'N',
"PKIStatus to be included in server response. Possible values: 0..6"},
{"failure", OPT_FAILURE, 'N',
"A single failure info bit number to include in server response, 0..26"},
{"failurebits", OPT_FAILUREBITS, 'N',
"Number representing failure bits to include in server response, 0..2^27 - 1"},
{"statusstring", OPT_STATUSSTRING, 's',
"Status string to be included in server response"},
{"send_error", OPT_SEND_ERROR, '-',
"Force server to reply with error message"},
{"send_unprotected", OPT_SEND_UNPROTECTED, '-',
"Send response messages without CMP-level protection"},
{"send_unprot_err", OPT_SEND_UNPROT_ERR, '-',
"In case of negative responses, server shall send unprotected error messages,"},
{OPT_MORE_STR, 0, 0,
"certificate responses (ip/cp/kup), and revocation responses (rp)."},
{OPT_MORE_STR, 0, 0,
"WARNING: This setting leads to behavior violating RFC 4210"},
{"accept_unprotected", OPT_ACCEPT_UNPROTECTED, '-',
"Accept missing or invalid protection of requests"},
{"accept_unprot_err", OPT_ACCEPT_UNPROT_ERR, '-',
"Accept unprotected error messages from client"},
{"accept_raverified", OPT_ACCEPT_RAVERIFIED, '-',
"Accept RAVERIFIED as proof-of-possession (POPO)"},
OPT_V_OPTIONS,
{NULL}
};
typedef union {
char **txt;
int *num;
long *num_long;
} varref;
static varref cmp_vars[] = { /* must be in same order as enumerated above! */
{&opt_config}, {&opt_section}, {(char **)&opt_verbosity},
{&opt_cmd_s}, {&opt_infotype_s}, {&opt_geninfo},
{&opt_newkey}, {&opt_newkeypass}, {&opt_subject}, {&opt_issuer},
{(char **)&opt_days}, {&opt_reqexts},
{&opt_sans}, {(char **)&opt_san_nodefault},
{&opt_policies}, {&opt_policy_oids}, {(char **)&opt_policy_oids_critical},
{(char **)&opt_popo}, {&opt_csr},
{&opt_out_trusted},
{(char **)&opt_implicit_confirm}, {(char **)&opt_disable_confirm},
{&opt_certout}, {&opt_chainout},
{&opt_oldcert}, {(char **)&opt_revreason},
#ifndef OPENSSL_NO_SOCK
{&opt_server}, {&opt_proxy}, {&opt_no_proxy},
#endif
{&opt_recipient}, {&opt_path}, {(char **)&opt_keep_alive},
{(char **)&opt_msg_timeout}, {(char **)&opt_total_timeout},
{&opt_trusted}, {&opt_untrusted}, {&opt_srvcert},
{&opt_expect_sender},
{(char **)&opt_ignore_keyusage}, {(char **)&opt_unprotected_errors},
{&opt_extracertsout}, {&opt_cacertsout},
{&opt_ref}, {&opt_secret},
{&opt_cert}, {&opt_own_trusted}, {&opt_key}, {&opt_keypass},
{&opt_digest}, {&opt_mac}, {&opt_extracerts},
{(char **)&opt_unprotected_requests},
{&opt_certform_s}, {&opt_keyform_s},
{&opt_otherpass},
#ifndef OPENSSL_NO_ENGINE
{&opt_engine},
#endif
#ifndef OPENSSL_NO_SOCK
{(char **)&opt_tls_used}, {&opt_tls_cert}, {&opt_tls_key},
{&opt_tls_keypass},
{&opt_tls_extra}, {&opt_tls_trusted}, {&opt_tls_host},
#endif
{(char **)&opt_batch}, {(char **)&opt_repeat},
{&opt_reqin}, {(char **)&opt_reqin_new_tid},
{&opt_reqout}, {&opt_rspin}, {&opt_rspout},
{(char **)&opt_use_mock_srv},
#ifndef OPENSSL_NO_SOCK
{&opt_port}, {(char **)&opt_max_msgs},
#endif
{&opt_srv_ref}, {&opt_srv_secret},
{&opt_srv_cert}, {&opt_srv_key}, {&opt_srv_keypass},
{&opt_srv_trusted}, {&opt_srv_untrusted},
{&opt_rsp_cert}, {&opt_rsp_extracerts}, {&opt_rsp_capubs},
{(char **)&opt_poll_count}, {(char **)&opt_check_after},
{(char **)&opt_grant_implicitconf},
{(char **)&opt_pkistatus}, {(char **)&opt_failure},
{(char **)&opt_failurebits}, {&opt_statusstring},
{(char **)&opt_send_error}, {(char **)&opt_send_unprotected},
{(char **)&opt_send_unprot_err}, {(char **)&opt_accept_unprotected},
{(char **)&opt_accept_unprot_err}, {(char **)&opt_accept_raverified},
{NULL}
};
#define FUNC (strcmp(OPENSSL_FUNC, "(unknown function)") == 0 \
? "CMP" : OPENSSL_FUNC)
#define CMP_print(bio, level, prefix, msg, a1, a2, a3) \
((void)(level > opt_verbosity ? 0 : \
(BIO_printf(bio, "%s:%s:%d:CMP %s: " msg "\n", \
FUNC, OPENSSL_FILE, OPENSSL_LINE, prefix, a1, a2, a3))))
#define CMP_DEBUG(m, a1, a2, a3) \
CMP_print(bio_out, OSSL_CMP_LOG_DEBUG, "debug", m, a1, a2, a3)
#define CMP_debug(msg) CMP_DEBUG(msg"%s%s%s", "", "", "")
#define CMP_debug1(msg, a1) CMP_DEBUG(msg"%s%s", a1, "", "")
#define CMP_debug2(msg, a1, a2) CMP_DEBUG(msg"%s", a1, a2, "")
#define CMP_debug3(msg, a1, a2, a3) CMP_DEBUG(msg, a1, a2, a3)
#define CMP_INFO(msg, a1, a2, a3) \
CMP_print(bio_out, OSSL_CMP_LOG_INFO, "info", msg, a1, a2, a3)
#define CMP_info(msg) CMP_INFO(msg"%s%s%s", "", "", "")
#define CMP_info1(msg, a1) CMP_INFO(msg"%s%s", a1, "", "")
#define CMP_info2(msg, a1, a2) CMP_INFO(msg"%s", a1, a2, "")
#define CMP_info3(msg, a1, a2, a3) CMP_INFO(msg, a1, a2, a3)
#define CMP_WARN(m, a1, a2, a3) \
CMP_print(bio_out, OSSL_CMP_LOG_WARNING, "warning", m, a1, a2, a3)
#define CMP_warn(msg) CMP_WARN(msg"%s%s%s", "", "", "")
#define CMP_warn1(msg, a1) CMP_WARN(msg"%s%s", a1, "", "")
#define CMP_warn2(msg, a1, a2) CMP_WARN(msg"%s", a1, a2, "")
#define CMP_warn3(msg, a1, a2, a3) CMP_WARN(msg, a1, a2, a3)
#define CMP_ERR(msg, a1, a2, a3) \
CMP_print(bio_err, OSSL_CMP_LOG_ERR, "error", msg, a1, a2, a3)
#define CMP_err(msg) CMP_ERR(msg"%s%s%s", "", "", "")
#define CMP_err1(msg, a1) CMP_ERR(msg"%s%s", a1, "", "")
#define CMP_err2(msg, a1, a2) CMP_ERR(msg"%s", a1, a2, "")
#define CMP_err3(msg, a1, a2, a3) CMP_ERR(msg, a1, a2, a3)
static int print_to_bio_out(const char *func, const char *file, int line,
OSSL_CMP_severity level, const char *msg)
{
return OSSL_CMP_print_to_bio(bio_out, func, file, line, level, msg);
}
static int print_to_bio_err(const char *func, const char *file, int line,
OSSL_CMP_severity level, const char *msg)
{
return OSSL_CMP_print_to_bio(bio_err, func, file, line, level, msg);
}
static int set_verbosity(int level)
{
if (level < OSSL_CMP_LOG_EMERG || level > OSSL_CMP_LOG_MAX) {
CMP_err1("Logging verbosity level %d out of range (0 .. 8)", level);
return 0;
}
opt_verbosity = level;
return 1;
}
static EVP_PKEY *load_key_pwd(const char *uri, int format,
const char *pass, ENGINE *eng, const char *desc)
{
char *pass_string = get_passwd(pass, desc);
EVP_PKEY *pkey = load_key(uri, format, 0, pass_string, eng, desc);
clear_free(pass_string);
return pkey;
}
static X509 *load_cert_pwd(const char *uri, const char *pass, const char *desc)
{
X509 *cert;
char *pass_string = get_passwd(pass, desc);
cert = load_cert_pass(uri, FORMAT_UNDEF, 0, pass_string, desc);
clear_free(pass_string);
return cert;
}
static X509_REQ *load_csr_autofmt(const char *infile, const char *desc)
{
X509_REQ *csr;
BIO *bio_bak = bio_err;
bio_err = NULL; /* do not show errors on more than one try */
csr = load_csr(infile, FORMAT_PEM, desc);
bio_err = bio_bak;
if (csr == NULL) {
ERR_clear_error();
csr = load_csr(infile, FORMAT_ASN1, desc);
}
if (csr == NULL) {
ERR_print_errors(bio_err);
BIO_printf(bio_err, "error: unable to load %s from file '%s'\n", desc,
infile);
} else {
EVP_PKEY *pkey = X509_REQ_get0_pubkey(csr);
int ret = do_X509_REQ_verify(csr, pkey, NULL /* vfyopts */);
if (pkey == NULL || ret < 0)
CMP_warn("error while verifying CSR self-signature");
else if (ret == 0)
CMP_warn("CSR self-signature does not match the contents");
}
return csr;
}
/* set expected host name/IP addr and clears the email addr in the given ts */
static int truststore_set_host_etc(X509_STORE *ts, const char *host)
{
X509_VERIFY_PARAM *ts_vpm = X509_STORE_get0_param(ts);
/* first clear any host names, IP, and email addresses */
if (!X509_VERIFY_PARAM_set1_host(ts_vpm, NULL, 0)
|| !X509_VERIFY_PARAM_set1_ip(ts_vpm, NULL, 0)
|| !X509_VERIFY_PARAM_set1_email(ts_vpm, NULL, 0))
return 0;
X509_VERIFY_PARAM_set_hostflags(ts_vpm,
X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT |
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
return (host != NULL && X509_VERIFY_PARAM_set1_ip_asc(ts_vpm, host))
|| X509_VERIFY_PARAM_set1_host(ts_vpm, host, 0);
}
/* write OSSL_CMP_MSG DER-encoded to the specified file name item */
static int write_PKIMESSAGE(const OSSL_CMP_MSG *msg, char **filenames)
{
char *file;
if (msg == NULL || filenames == NULL) {
CMP_err("NULL arg to write_PKIMESSAGE");
return 0;
}
if (*filenames == NULL) {
CMP_err("not enough file names provided for writing PKIMessage");
return 0;
}
file = *filenames;
*filenames = next_item(file);
if (OSSL_CMP_MSG_write(file, msg) < 0) {
CMP_err1("cannot write PKIMessage to file '%s'", file);
return 0;
}
return 1;
}
/* read DER-encoded OSSL_CMP_MSG from the specified file name item */
-static OSSL_CMP_MSG *read_PKIMESSAGE(char **filenames)
+static OSSL_CMP_MSG *read_PKIMESSAGE(const char *desc, char **filenames)
{
char *file;
OSSL_CMP_MSG *ret;
- if (filenames == NULL) {
+ if (filenames == NULL || desc == NULL) {
CMP_err("NULL arg to read_PKIMESSAGE");
return NULL;
}
if (*filenames == NULL) {
CMP_err("not enough file names provided for reading PKIMessage");
return NULL;
}
file = *filenames;
*filenames = next_item(file);
ret = OSSL_CMP_MSG_read(file, app_get0_libctx(), app_get0_propq());
if (ret == NULL)
CMP_err1("cannot read PKIMessage from file '%s'", file);
+ else
+ CMP_info2("%s %s", desc, file);
return ret;
}
/*-
* Sends the PKIMessage req and on success place the response in *res
* basically like OSSL_CMP_MSG_http_perform(), but in addition allows
* to dump the sequence of requests and responses to files and/or
* to take the sequence of requests and responses from files.
*/
static OSSL_CMP_MSG *read_write_req_resp(OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_MSG *req_new = NULL;
OSSL_CMP_MSG *res = NULL;
OSSL_CMP_PKIHEADER *hdr;
const char *prev_opt_rspin = opt_rspin;
if (req != NULL && opt_reqout != NULL
&& !write_PKIMESSAGE(req, &opt_reqout))
goto err;
if (opt_reqin != NULL && opt_rspin == NULL) {
- if ((req_new = read_PKIMESSAGE(&opt_reqin)) == NULL)
+ if ((req_new = read_PKIMESSAGE("actually sending", &opt_reqin)) == NULL)
goto err;
/*-
* The transaction ID in req_new read from opt_reqin may not be fresh.
* In this case the server may complain "Transaction id already in use."
* The following workaround unfortunately requires re-protection.
*/
if (opt_reqin_new_tid
&& !OSSL_CMP_MSG_update_transactionID(ctx, req_new))
goto err;
+
+ /*
+ * Except for first request, need to satisfy recipNonce check by server.
+ * Unfortunately requires re-protection if protection is required.
+ */
+ if (!OSSL_CMP_MSG_update_recipNonce(ctx, req_new))
+ goto err;
}
if (opt_rspin != NULL) {
- res = read_PKIMESSAGE(&opt_rspin);
+ res = read_PKIMESSAGE("actually using", &opt_rspin);
} else {
- const OSSL_CMP_MSG *actual_req = opt_reqin != NULL ? req_new : req;
+ const OSSL_CMP_MSG *actual_req = req_new != NULL ? req_new : req;
- res = opt_use_mock_srv
- ? OSSL_CMP_CTX_server_perform(ctx, actual_req)
- : OSSL_CMP_MSG_http_perform(ctx, actual_req);
+ if (opt_use_mock_srv) {
+ if (rspin_in_use)
+ CMP_warn("too few -rspin filename arguments; resorting to using mock server");
+ res = OSSL_CMP_CTX_server_perform(ctx, actual_req);
+ } else {
+#ifndef OPENSSL_NO_SOCK
+ if (opt_server == NULL) {
+ CMP_err("missing -server or -use_mock_srv option, or too few -rspin filename arguments");
+ goto err;
+ }
+ if (rspin_in_use)
+ CMP_warn("too few -rspin filename arguments; resorting to contacting server");
+ res = OSSL_CMP_MSG_http_perform(ctx, actual_req);
+#else
+ CMP_err("-server not supported on no-sock build; missing -use_mock_srv option or too few -rspin filename arguments");
+#endif
+ }
+ rspin_in_use = 0;
}
if (res == NULL)
goto err;
- if (opt_reqin != NULL || prev_opt_rspin != NULL) {
- /* need to satisfy nonce and transactionID checks */
+ if (req_new != NULL || prev_opt_rspin != NULL) {
+ /* need to satisfy nonce and transactionID checks by client */
ASN1_OCTET_STRING *nonce;
ASN1_OCTET_STRING *tid;
hdr = OSSL_CMP_MSG_get0_header(res);
nonce = OSSL_CMP_HDR_get0_recipNonce(hdr);
tid = OSSL_CMP_HDR_get0_transactionID(hdr);
if (!OSSL_CMP_CTX_set1_senderNonce(ctx, nonce)
|| !OSSL_CMP_CTX_set1_transactionID(ctx, tid)) {
OSSL_CMP_MSG_free(res);
res = NULL;
goto err;
}
}
if (opt_rspout != NULL && !write_PKIMESSAGE(res, &opt_rspout)) {
OSSL_CMP_MSG_free(res);
res = NULL;
}
err:
OSSL_CMP_MSG_free(req_new);
return res;
}
static int set_name(const char *str,
int (*set_fn) (OSSL_CMP_CTX *ctx, const X509_NAME *name),
OSSL_CMP_CTX *ctx, const char *desc)
{
if (str != NULL) {
X509_NAME *n = parse_name(str, MBSTRING_ASC, 1, desc);
if (n == NULL)
return 0;
if (!(*set_fn) (ctx, n)) {
X509_NAME_free(n);
CMP_err("out of memory");
return 0;
}
X509_NAME_free(n);
}
return 1;
}
static int set_gennames(OSSL_CMP_CTX *ctx, char *names, const char *desc)
{
char *next;
for (; names != NULL; names = next) {
GENERAL_NAME *n;
next = next_item(names);
if (strcmp(names, "critical") == 0) {
(void)OSSL_CMP_CTX_set_option(ctx,
OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL,
1);
continue;
}
/* try IP address first, then URI or domain name */
(void)ERR_set_mark();
n = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_IPADD, names, 0);
if (n == NULL)
n = a2i_GENERAL_NAME(NULL, NULL, NULL,
strchr(names, ':') != NULL ? GEN_URI : GEN_DNS,
names, 0);
(void)ERR_pop_to_mark();
if (n == NULL) {
CMP_err2("bad syntax of %s '%s'", desc, names);
return 0;
}
if (!OSSL_CMP_CTX_push1_subjectAltName(ctx, n)) {
GENERAL_NAME_free(n);
CMP_err("out of memory");
return 0;
}
GENERAL_NAME_free(n);
}
return 1;
}
static X509_STORE *load_trusted(char *input, int for_new_cert, const char *desc)
{
X509_STORE *ts = load_certstore(input, opt_otherpass, desc, vpm);
if (ts == NULL)
return NULL;
X509_STORE_set_verify_cb(ts, X509_STORE_CTX_print_verify_cb);
/* copy vpm to store */
if (X509_STORE_set1_param(ts, vpm /* may be NULL */)
&& (for_new_cert || truststore_set_host_etc(ts, NULL)))
return ts;
BIO_printf(bio_err, "error setting verification parameters for %s\n", desc);
OSSL_CMP_CTX_print_errors(cmp_ctx);
X509_STORE_free(ts);
return NULL;
}
typedef int (*add_X509_stack_fn_t)(void *ctx, const STACK_OF(X509) *certs);
static int setup_certs(char *files, const char *desc, void *ctx,
add_X509_stack_fn_t set1_fn)
{
STACK_OF(X509) *certs;
int ok;
if (files == NULL)
return 1;
if ((certs = load_certs_multifile(files, opt_otherpass, desc, vpm)) == NULL)
return 0;
ok = (*set1_fn)(ctx, certs);
sk_X509_pop_free(certs, X509_free);
return ok;
}
/*
* parse and transform some options, checking their syntax.
* Returns 1 on success, 0 on error
*/
static int transform_opts(void)
{
if (opt_cmd_s != NULL) {
if (!strcmp(opt_cmd_s, "ir")) {
opt_cmd = CMP_IR;
} else if (!strcmp(opt_cmd_s, "kur")) {
opt_cmd = CMP_KUR;
} else if (!strcmp(opt_cmd_s, "cr")) {
opt_cmd = CMP_CR;
} else if (!strcmp(opt_cmd_s, "p10cr")) {
opt_cmd = CMP_P10CR;
} else if (!strcmp(opt_cmd_s, "rr")) {
opt_cmd = CMP_RR;
} else if (!strcmp(opt_cmd_s, "genm")) {
opt_cmd = CMP_GENM;
} else {
CMP_err1("unknown cmp command '%s'", opt_cmd_s);
return 0;
}
} else {
CMP_err("no cmp command to execute");
return 0;
}
#ifndef OPENSSL_NO_ENGINE
# define FORMAT_OPTIONS (OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_ENGINE)
#else
# define FORMAT_OPTIONS (OPT_FMT_PEMDER | OPT_FMT_PKCS12)
#endif
if (opt_keyform_s != NULL
&& !opt_format(opt_keyform_s, FORMAT_OPTIONS, &opt_keyform)) {
CMP_err("unknown option given for key loading format");
return 0;
}
#undef FORMAT_OPTIONS
if (opt_certform_s != NULL
&& !opt_format(opt_certform_s, OPT_FMT_PEMDER, &opt_certform)) {
CMP_err("unknown option given for certificate storing format");
return 0;
}
return 1;
}
static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
{
OSSL_CMP_CTX *ctx; /* extra CMP (client) ctx partly used by server */
OSSL_CMP_SRV_CTX *srv_ctx = ossl_cmp_mock_srv_new(app_get0_libctx(),
app_get0_propq());
if (srv_ctx == NULL)
return NULL;
ctx = OSSL_CMP_SRV_CTX_get0_cmp_ctx(srv_ctx);
if (opt_srv_ref == NULL) {
if (opt_srv_cert == NULL) {
/* opt_srv_cert should determine the sender */
CMP_err("must give -srv_ref for mock server if no -srv_cert given");
goto err;
}
} else {
if (!OSSL_CMP_CTX_set1_referenceValue(ctx, (unsigned char *)opt_srv_ref,
strlen(opt_srv_ref)))
goto err;
}
if (opt_srv_secret != NULL) {
int res;
char *pass_str = get_passwd(opt_srv_secret, "PBMAC secret of mock server");
if (pass_str != NULL) {
cleanse(opt_srv_secret);
res = OSSL_CMP_CTX_set1_secretValue(ctx, (unsigned char *)pass_str,
strlen(pass_str));
clear_free(pass_str);
if (res == 0)
goto err;
}
} else if (opt_srv_cert == NULL) {
- CMP_err("mock server credentials must be given if -use_mock_srv or -port is used");
+ CMP_err("server credentials (-srv_secret or -srv_cert) must be given if -use_mock_srv or -port is used");
goto err;
} else {
- CMP_warn("mock server will not be able to handle PBM-protected requests since -srv_secret is not given");
+ CMP_warn("server will not be able to handle PBM-protected requests since -srv_secret is not given");
}
if (opt_srv_secret == NULL
&& ((opt_srv_cert == NULL) != (opt_srv_key == NULL))) {
CMP_err("must give both -srv_cert and -srv_key options or neither");
goto err;
}
if (opt_srv_cert != NULL) {
X509 *srv_cert = load_cert_pwd(opt_srv_cert, opt_srv_keypass,
"certificate of the mock server");
if (srv_cert == NULL || !OSSL_CMP_CTX_set1_cert(ctx, srv_cert)) {
X509_free(srv_cert);
goto err;
}
X509_free(srv_cert);
}
if (opt_srv_key != NULL) {
EVP_PKEY *pkey = load_key_pwd(opt_srv_key, opt_keyform,
opt_srv_keypass,
engine, "private key for mock server cert");
if (pkey == NULL || !OSSL_CMP_CTX_set1_pkey(ctx, pkey)) {
EVP_PKEY_free(pkey);
goto err;
}
EVP_PKEY_free(pkey);
}
cleanse(opt_srv_keypass);
if (opt_srv_trusted != NULL) {
X509_STORE *ts =
load_trusted(opt_srv_trusted, 0, "certs trusted by mock server");
if (ts == NULL || !OSSL_CMP_CTX_set0_trustedStore(ctx, ts)) {
X509_STORE_free(ts);
goto err;
}
} else {
CMP_warn("mock server will not be able to handle signature-protected requests since -srv_trusted is not given");
}
if (!setup_certs(opt_srv_untrusted,
"untrusted certificates for mock server", ctx,
(add_X509_stack_fn_t)OSSL_CMP_CTX_set1_untrusted))
goto err;
if (opt_rsp_cert == NULL) {
CMP_warn("no -rsp_cert given for mock server");
} else {
X509 *cert = load_cert_pwd(opt_rsp_cert, opt_keypass,
"cert to be returned by the mock server");
if (cert == NULL)
goto err;
/* from server perspective the server is the client */
if (!ossl_cmp_mock_srv_set1_certOut(srv_ctx, cert)) {
X509_free(cert);
goto err;
}
X509_free(cert);
}
if (!setup_certs(opt_rsp_extracerts,
"CMP extra certificates for mock server", srv_ctx,
(add_X509_stack_fn_t)ossl_cmp_mock_srv_set1_chainOut))
goto err;
if (!setup_certs(opt_rsp_capubs, "caPubs for mock server", srv_ctx,
(add_X509_stack_fn_t)ossl_cmp_mock_srv_set1_caPubsOut))
goto err;
(void)ossl_cmp_mock_srv_set_pollCount(srv_ctx, opt_poll_count);
(void)ossl_cmp_mock_srv_set_checkAfterTime(srv_ctx, opt_check_after);
if (opt_grant_implicitconf)
(void)OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(srv_ctx, 1);
if (opt_failure != INT_MIN) { /* option has been set explicity */
if (opt_failure < 0 || OSSL_CMP_PKIFAILUREINFO_MAX < opt_failure) {
CMP_err1("-failure out of range, should be >= 0 and <= %d",
OSSL_CMP_PKIFAILUREINFO_MAX);
goto err;
}
if (opt_failurebits != 0)
CMP_warn("-failurebits overrides -failure");
else
opt_failurebits = 1 << opt_failure;
}
if ((unsigned)opt_failurebits > OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN) {
CMP_err("-failurebits out of range");
goto err;
}
if (!ossl_cmp_mock_srv_set_statusInfo(srv_ctx, opt_pkistatus,
opt_failurebits, opt_statusstring))
goto err;
if (opt_send_error)
- (void)ossl_cmp_mock_srv_set_send_error(srv_ctx, 1);
+ (void)ossl_cmp_mock_srv_set_sendError(srv_ctx, 1);
if (opt_send_unprotected)
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_SEND, 1);
if (opt_send_unprot_err)
(void)OSSL_CMP_SRV_CTX_set_send_unprotected_errors(srv_ctx, 1);
if (opt_accept_unprotected)
(void)OSSL_CMP_SRV_CTX_set_accept_unprotected(srv_ctx, 1);
if (opt_accept_unprot_err)
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS, 1);
if (opt_accept_raverified)
(void)OSSL_CMP_SRV_CTX_set_accept_raverified(srv_ctx, 1);
return srv_ctx;
err:
ossl_cmp_mock_srv_free(srv_ctx);
return NULL;
}
/*
* set up verification aspects of OSSL_CMP_CTX w.r.t. opts from config file/CLI.
* Returns pointer on success, NULL on error
*/
static int setup_verification_ctx(OSSL_CMP_CTX *ctx)
{
if (!setup_certs(opt_untrusted, "untrusted certificates", ctx,
(add_X509_stack_fn_t)OSSL_CMP_CTX_set1_untrusted))
return 0;
if (opt_srvcert != NULL || opt_trusted != NULL) {
X509 *srvcert;
X509_STORE *ts;
int ok;
if (opt_srvcert != NULL) {
if (opt_trusted != NULL) {
CMP_warn("-trusted option is ignored since -srvcert option is present");
opt_trusted = NULL;
}
if (opt_recipient != NULL) {
CMP_warn("-recipient option is ignored since -srvcert option is present");
opt_recipient = NULL;
}
srvcert = load_cert_pwd(opt_srvcert, opt_otherpass,
"directly trusted CMP server certificate");
ok = srvcert != NULL && OSSL_CMP_CTX_set1_srvCert(ctx, srvcert);
X509_free(srvcert);
if (!ok)
return 0;
}
if (opt_trusted != NULL) {
/*
* the 0 arg below clears any expected host/ip/email address;
* opt_expect_sender is used instead
*/
ts = load_trusted(opt_trusted, 0, "certs trusted by client");
if (ts == NULL || !OSSL_CMP_CTX_set0_trustedStore(ctx, ts)) {
X509_STORE_free(ts);
return 0;
}
}
}
if (opt_ignore_keyusage)
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_IGNORE_KEYUSAGE, 1);
if (opt_unprotected_errors)
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS, 1);
if (opt_out_trusted != NULL) { /* for use in OSSL_CMP_certConf_cb() */
X509_VERIFY_PARAM *out_vpm = NULL;
X509_STORE *out_trusted =
load_trusted(opt_out_trusted, 1,
"trusted certs for verifying newly enrolled cert");
if (out_trusted == NULL)
return 0;
/* ignore any -attime here, new certs are current anyway */
out_vpm = X509_STORE_get0_param(out_trusted);
X509_VERIFY_PARAM_clear_flags(out_vpm, X509_V_FLAG_USE_CHECK_TIME);
(void)OSSL_CMP_CTX_set_certConf_cb_arg(ctx, out_trusted);
}
if (opt_disable_confirm)
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_DISABLE_CONFIRM, 1);
if (opt_implicit_confirm)
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM, 1);
return 1;
}
#ifndef OPENSSL_NO_SOCK
/*
* set up ssl_ctx for the OSSL_CMP_CTX based on options from config file/CLI.
* Returns pointer on success, NULL on error
*/
static SSL_CTX *setup_ssl_ctx(OSSL_CMP_CTX *ctx, const char *host,
ENGINE *engine)
{
STACK_OF(X509) *untrusted = OSSL_CMP_CTX_get0_untrusted(ctx);
EVP_PKEY *pkey = NULL;
X509_STORE *trust_store = NULL;
SSL_CTX *ssl_ctx;
int i;
ssl_ctx = SSL_CTX_new(TLS_client_method());
if (ssl_ctx == NULL)
return NULL;
if (opt_tls_trusted != NULL) {
trust_store = load_trusted(opt_tls_trusted, 0, "trusted TLS certs");
if (trust_store == NULL)
goto err;
SSL_CTX_set_cert_store(ssl_ctx, trust_store);
}
if (opt_tls_cert != NULL && opt_tls_key != NULL) {
X509 *cert;
STACK_OF(X509) *certs = NULL;
int ok;
if (!load_cert_certs(opt_tls_cert, &cert, &certs, 0, opt_tls_keypass,
"TLS client certificate (optionally with chain)",
vpm))
/* need opt_tls_keypass if opt_tls_cert is encrypted PKCS#12 file */
goto err;
ok = SSL_CTX_use_certificate(ssl_ctx, cert) > 0;
X509_free(cert);
/*
* Any further certs and any untrusted certs are used for constructing
* the chain to be provided with the TLS client cert to the TLS server.
*/
if (!ok || !SSL_CTX_set0_chain(ssl_ctx, certs)) {
CMP_err1("unable to use client TLS certificate file '%s'",
opt_tls_cert);
sk_X509_pop_free(certs, X509_free);
goto err;
}
for (i = 0; i < sk_X509_num(untrusted); i++) {
cert = sk_X509_value(untrusted, i);
if (!SSL_CTX_add1_chain_cert(ssl_ctx, cert)) {
CMP_err("could not add untrusted cert to TLS client cert chain");
goto err;
}
}
{
X509_VERIFY_PARAM *tls_vpm = NULL;
unsigned long bak_flags = 0; /* compiler warns without init */
if (trust_store != NULL) {
tls_vpm = X509_STORE_get0_param(trust_store);
bak_flags = X509_VERIFY_PARAM_get_flags(tls_vpm);
/* disable any cert status/revocation checking etc. */
X509_VERIFY_PARAM_clear_flags(tls_vpm,
~(X509_V_FLAG_USE_CHECK_TIME
- | X509_V_FLAG_NO_CHECK_TIME));
+ | X509_V_FLAG_NO_CHECK_TIME
+ | X509_V_FLAG_PARTIAL_CHAIN
+ | X509_V_FLAG_POLICY_CHECK));
}
CMP_debug("trying to build cert chain for own TLS cert");
if (SSL_CTX_build_cert_chain(ssl_ctx,
SSL_BUILD_CHAIN_FLAG_UNTRUSTED |
SSL_BUILD_CHAIN_FLAG_NO_ROOT)) {
CMP_debug("success building cert chain for own TLS cert");
} else {
OSSL_CMP_CTX_print_errors(ctx);
CMP_warn("could not build cert chain for own TLS cert");
}
if (trust_store != NULL)
X509_VERIFY_PARAM_set_flags(tls_vpm, bak_flags);
}
/* If present we append to the list also the certs from opt_tls_extra */
if (opt_tls_extra != NULL) {
STACK_OF(X509) *tls_extra = load_certs_multifile(opt_tls_extra,
opt_otherpass,
"extra certificates for TLS",
vpm);
int res = 1;
if (tls_extra == NULL)
goto err;
for (i = 0; i < sk_X509_num(tls_extra); i++) {
cert = sk_X509_value(tls_extra, i);
if (res != 0)
res = SSL_CTX_add_extra_chain_cert(ssl_ctx, cert);
if (res == 0)
X509_free(cert);
}
sk_X509_free(tls_extra);
if (res == 0) {
BIO_printf(bio_err, "error: unable to add TLS extra certs\n");
goto err;
}
}
pkey = load_key_pwd(opt_tls_key, opt_keyform, opt_tls_keypass,
engine, "TLS client private key");
cleanse(opt_tls_keypass);
if (pkey == NULL)
goto err;
/*
* verify the key matches the cert,
* not using SSL_CTX_check_private_key(ssl_ctx)
* because it gives poor and sometimes misleading diagnostics
*/
if (!X509_check_private_key(SSL_CTX_get0_certificate(ssl_ctx),
pkey)) {
CMP_err2("TLS private key '%s' does not match the TLS certificate '%s'\n",
opt_tls_key, opt_tls_cert);
EVP_PKEY_free(pkey);
pkey = NULL; /* otherwise, for some reason double free! */
goto err;
}
if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) <= 0) {
CMP_err1("unable to use TLS client private key '%s'", opt_tls_key);
EVP_PKEY_free(pkey);
pkey = NULL; /* otherwise, for some reason double free! */
goto err;
}
EVP_PKEY_free(pkey); /* we do not need the handle any more */
}
if (opt_tls_trusted != NULL) {
/* enable and parameterize server hostname/IP address check */
if (!truststore_set_host_etc(trust_store,
opt_tls_host != NULL ? opt_tls_host : host))
goto err;
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
}
return ssl_ctx;
err:
SSL_CTX_free(ssl_ctx);
return NULL;
}
#endif /* OPENSSL_NO_SOCK */
/*
* set up protection aspects of OSSL_CMP_CTX based on options from config
* file/CLI while parsing options and checking their consistency.
* Returns 1 on success, 0 on error
*/
static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
{
if (!opt_unprotected_requests && opt_secret == NULL && opt_key == NULL) {
CMP_err("must give -key or -secret unless -unprotected_requests is used");
return 0;
}
if (opt_ref == NULL && opt_cert == NULL && opt_subject == NULL) {
/* cert or subject should determine the sender */
CMP_err("must give -ref if no -cert and no -subject given");
return 0;
}
if (!opt_secret && ((opt_cert == NULL) != (opt_key == NULL))) {
CMP_err("must give both -cert and -key options or neither");
return 0;
}
if (opt_secret != NULL) {
char *pass_string = get_passwd(opt_secret, "PBMAC");
int res;
if (pass_string != NULL) {
cleanse(opt_secret);
res = OSSL_CMP_CTX_set1_secretValue(ctx,
(unsigned char *)pass_string,
strlen(pass_string));
clear_free(pass_string);
if (res == 0)
return 0;
}
if (opt_cert != NULL || opt_key != NULL)
CMP_warn("-cert and -key not used for protection since -secret is given");
}
if (opt_ref != NULL
&& !OSSL_CMP_CTX_set1_referenceValue(ctx, (unsigned char *)opt_ref,
strlen(opt_ref)))
return 0;
if (opt_key != NULL) {
EVP_PKEY *pkey = load_key_pwd(opt_key, opt_keyform, opt_keypass, engine,
"private key for CMP client certificate");
if (pkey == NULL || !OSSL_CMP_CTX_set1_pkey(ctx, pkey)) {
EVP_PKEY_free(pkey);
return 0;
}
EVP_PKEY_free(pkey);
}
if (opt_secret == NULL && opt_srvcert == NULL && opt_trusted == NULL)
CMP_warn("will not authenticate server due to missing -secret, -trusted, or -srvcert");
if (opt_cert != NULL) {
X509 *cert;
STACK_OF(X509) *certs = NULL;
X509_STORE *own_trusted = NULL;
int ok;
if (!load_cert_certs(opt_cert, &cert, &certs, 0, opt_keypass,
"CMP client certificate (optionally with chain)",
vpm))
/* opt_keypass is needed if opt_cert is an encrypted PKCS#12 file */
return 0;
ok = OSSL_CMP_CTX_set1_cert(ctx, cert);
X509_free(cert);
if (!ok) {
CMP_err("out of memory");
} else {
if (opt_own_trusted != NULL) {
own_trusted = load_trusted(opt_own_trusted, 0,
"trusted certs for verifying own CMP signer cert");
ok = own_trusted != NULL;
}
ok = ok && OSSL_CMP_CTX_build_cert_chain(ctx, own_trusted, certs);
}
X509_STORE_free(own_trusted);
sk_X509_pop_free(certs, X509_free);
if (!ok)
return 0;
} else if (opt_own_trusted != NULL) {
CMP_warn("-own_trusted option is ignored without -cert");
}
if (!setup_certs(opt_extracerts, "extra certificates for CMP", ctx,
(add_X509_stack_fn_t)OSSL_CMP_CTX_set1_extraCertsOut))
return 0;
cleanse(opt_otherpass);
if (opt_unprotected_requests)
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_SEND, 1);
if (opt_digest != NULL) {
int digest = OBJ_ln2nid(opt_digest);
if (digest == NID_undef) {
CMP_err1("digest algorithm name not recognized: '%s'", opt_digest);
return 0;
}
if (!OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_DIGEST_ALGNID, digest)
|| !OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_OWF_ALGNID, digest)) {
CMP_err1("digest algorithm name not supported: '%s'", opt_digest);
return 0;
}
}
if (opt_mac != NULL) {
int mac = OBJ_ln2nid(opt_mac);
if (mac == NID_undef) {
CMP_err1("MAC algorithm name not recognized: '%s'", opt_mac);
return 0;
}
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_MAC_ALGNID, mac);
}
return 1;
}
/*
* set up IR/CR/KUR/CertConf/RR specific parts of the OSSL_CMP_CTX
* based on options from config file/CLI.
* Returns pointer on success, NULL on error
*/
static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
{
X509_REQ *csr = NULL;
X509_EXTENSIONS *exts = NULL;
X509V3_CTX ext_ctx;
if (opt_subject == NULL
&& opt_csr == NULL && opt_oldcert == NULL && opt_cert == NULL
&& opt_cmd != CMP_RR && opt_cmd != CMP_GENM)
CMP_warn("no -subject given; no -csr or -oldcert or -cert available for fallback");
if (opt_cmd == CMP_IR || opt_cmd == CMP_CR || opt_cmd == CMP_KUR) {
- if (opt_newkey == NULL && opt_key == NULL && opt_csr == NULL) {
- CMP_err("missing -newkey (or -key) to be certified and no -csr given");
+ if (opt_newkey == NULL
+ && opt_key == NULL && opt_csr == NULL && opt_oldcert == NULL) {
+ CMP_err("missing -newkey (or -key) to be certified and no -csr, -oldcert, or -cert given for fallback public key");
return 0;
}
+ if (opt_newkey == NULL
+ && opt_popo != OSSL_CRMF_POPO_NONE
+ && opt_popo != OSSL_CRMF_POPO_RAVERIFIED) {
+ if (opt_csr != NULL) {
+ CMP_err1("no -newkey option given with private key for POPO, -csr option only provides public key%s",
+ opt_key == NULL ? "" :
+ ", and -key option superseded by by -csr");
+ return 0;
+ }
+ if (opt_key == NULL) {
+ CMP_err("missing -newkey (or -key) option for POPO");
+ return 0;
+ }
+ }
if (opt_certout == NULL) {
CMP_err("-certout not given, nowhere to save newly enrolled certificate");
return 0;
}
if (!set_name(opt_subject, OSSL_CMP_CTX_set1_subjectName, ctx, "subject")
|| !set_name(opt_issuer, OSSL_CMP_CTX_set1_issuer, ctx, "issuer"))
return 0;
} else {
const char *msg = "option is ignored for commands other than 'ir', 'cr', and 'kur'";
if (opt_subject != NULL) {
if (opt_ref == NULL && opt_cert == NULL) {
/* use subject as default sender unless oldcert subject is used */
if (!set_name(opt_subject, OSSL_CMP_CTX_set1_subjectName, ctx, "subject"))
return 0;
} else {
CMP_warn1("-subject %s since -ref or -cert is given", msg);
}
}
if (opt_issuer != NULL)
CMP_warn1("-issuer %s", msg);
if (opt_reqexts != NULL)
CMP_warn1("-reqexts %s", msg);
if (opt_san_nodefault)
CMP_warn1("-san_nodefault %s", msg);
if (opt_sans != NULL)
CMP_warn1("-sans %s", msg);
if (opt_policies != NULL)
CMP_warn1("-policies %s", msg);
if (opt_policy_oids != NULL)
CMP_warn1("-policy_oids %s", msg);
}
if (opt_cmd == CMP_KUR) {
char *ref_cert = opt_oldcert != NULL ? opt_oldcert : opt_cert;
if (ref_cert == NULL && opt_csr == NULL) {
CMP_err("missing -oldcert for certificate to be updated and no -csr given");
return 0;
}
if (opt_subject != NULL)
CMP_warn2("given -subject '%s' overrides the subject of '%s' for KUR",
opt_subject, ref_cert != NULL ? ref_cert : opt_csr);
}
if (opt_cmd == CMP_RR) {
if (opt_oldcert == NULL && opt_csr == NULL) {
CMP_err("missing -oldcert for certificate to be revoked and no -csr given");
return 0;
}
if (opt_oldcert != NULL && opt_csr != NULL)
CMP_warn("ignoring -csr since certificate to be revoked is given");
}
if (opt_cmd == CMP_P10CR && opt_csr == NULL) {
CMP_err("missing PKCS#10 CSR for p10cr");
return 0;
}
if (opt_recipient == NULL && opt_srvcert == NULL && opt_issuer == NULL
&& opt_oldcert == NULL && opt_cert == NULL)
CMP_warn("missing -recipient, -srvcert, -issuer, -oldcert or -cert; recipient will be set to \"NULL-DN\"");
if (opt_cmd == CMP_P10CR || opt_cmd == CMP_RR) {
const char *msg = "option is ignored for 'p10cr' and 'rr' commands";
if (opt_newkeypass != NULL)
CMP_warn1("-newkeytype %s", msg);
if (opt_newkey != NULL)
CMP_warn1("-newkey %s", msg);
if (opt_days != 0)
CMP_warn1("-days %s", msg);
if (opt_popo != OSSL_CRMF_POPO_NONE - 1)
CMP_warn1("-popo %s", msg);
} else if (opt_newkey != NULL) {
const char *file = opt_newkey;
const int format = opt_keyform;
const char *pass = opt_newkeypass;
const char *desc = "new private key for cert to be enrolled";
EVP_PKEY *pkey;
int priv = 1;
BIO *bio_bak = bio_err;
bio_err = NULL; /* suppress diagnostics on first try loading key */
pkey = load_key_pwd(file, format, pass, engine, desc);
bio_err = bio_bak;
if (pkey == NULL) {
ERR_clear_error();
desc = opt_csr == NULL
? "fallback public key for cert to be enrolled"
: "public key for checking cert resulting from p10cr";
pkey = load_pubkey(file, format, 0, pass, engine, desc);
priv = 0;
}
cleanse(opt_newkeypass);
if (pkey == NULL || !OSSL_CMP_CTX_set0_newPkey(ctx, priv, pkey)) {
EVP_PKEY_free(pkey);
return 0;
}
}
if (opt_days > 0
&& !OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_VALIDITY_DAYS,
opt_days)) {
CMP_err("could not set requested cert validity period");
return 0;
}
if (opt_policies != NULL && opt_policy_oids != NULL) {
CMP_err("cannot have policies both via -policies and via -policy_oids");
return 0;
}
if (opt_csr != NULL) {
if (opt_cmd == CMP_GENM) {
CMP_warn("-csr option is ignored for command 'genm'");
} else {
if ((csr = load_csr_autofmt(opt_csr, "PKCS#10 CSR")) == NULL)
return 0;
if (!OSSL_CMP_CTX_set1_p10CSR(ctx, csr))
goto oom;
}
}
if (opt_reqexts != NULL || opt_policies != NULL) {
if ((exts = sk_X509_EXTENSION_new_null()) == NULL)
goto oom;
X509V3_set_ctx(&ext_ctx, NULL, NULL, csr, NULL, X509V3_CTX_REPLACE);
X509V3_set_nconf(&ext_ctx, conf);
if (opt_reqexts != NULL
&& !X509V3_EXT_add_nconf_sk(conf, &ext_ctx, opt_reqexts, &exts)) {
CMP_err1("cannot load certificate request extension section '%s'",
opt_reqexts);
goto exts_err;
}
if (opt_policies != NULL
&& !X509V3_EXT_add_nconf_sk(conf, &ext_ctx, opt_policies, &exts)) {
CMP_err1("cannot load policy cert request extension section '%s'",
opt_policies);
goto exts_err;
}
OSSL_CMP_CTX_set0_reqExtensions(ctx, exts);
}
X509_REQ_free(csr);
/* After here, must not goto oom/exts_err */
if (OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) && opt_sans != NULL) {
CMP_err("cannot have Subject Alternative Names both via -reqexts and via -sans");
return 0;
}
if (!set_gennames(ctx, opt_sans, "Subject Alternative Name"))
return 0;
if (opt_san_nodefault) {
if (opt_sans != NULL)
CMP_warn("-opt_san_nodefault has no effect when -sans is used");
(void)OSSL_CMP_CTX_set_option(ctx,
OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT, 1);
}
if (opt_policy_oids_critical) {
if (opt_policy_oids == NULL)
CMP_warn("-opt_policy_oids_critical has no effect unless -policy_oids is given");
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_POLICIES_CRITICAL, 1);
}
while (opt_policy_oids != NULL) {
ASN1_OBJECT *policy;
POLICYINFO *pinfo;
char *next = next_item(opt_policy_oids);
if ((policy = OBJ_txt2obj(opt_policy_oids, 1)) == 0) {
CMP_err1("unknown policy OID '%s'", opt_policy_oids);
return 0;
}
if ((pinfo = POLICYINFO_new()) == NULL) {
ASN1_OBJECT_free(policy);
return 0;
}
pinfo->policyid = policy;
if (!OSSL_CMP_CTX_push0_policy(ctx, pinfo)) {
CMP_err1("cannot add policy with OID '%s'", opt_policy_oids);
POLICYINFO_free(pinfo);
return 0;
}
opt_policy_oids = next;
}
if (opt_popo >= OSSL_CRMF_POPO_NONE)
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_POPO_METHOD, opt_popo);
if (opt_oldcert != NULL) {
if (opt_cmd == CMP_GENM) {
CMP_warn("-oldcert option is ignored for command 'genm'");
} else {
X509 *oldcert = load_cert_pwd(opt_oldcert, opt_keypass,
opt_cmd == CMP_KUR ?
"certificate to be updated" :
opt_cmd == CMP_RR ?
"certificate to be revoked" :
"reference certificate (oldcert)");
/* opt_keypass needed if opt_oldcert is an encrypted PKCS#12 file */
if (oldcert == NULL)
return 0;
if (!OSSL_CMP_CTX_set1_oldCert(ctx, oldcert)) {
X509_free(oldcert);
CMP_err("out of memory");
return 0;
}
X509_free(oldcert);
}
}
cleanse(opt_keypass);
if (opt_revreason > CRL_REASON_NONE)
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_REVOCATION_REASON,
opt_revreason);
return 1;
oom:
CMP_err("out of memory");
exts_err:
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
X509_REQ_free(csr);
return 0;
}
static int handle_opt_geninfo(OSSL_CMP_CTX *ctx)
{
long value;
ASN1_OBJECT *type;
ASN1_INTEGER *aint;
ASN1_TYPE *val;
OSSL_CMP_ITAV *itav;
char *endstr;
char *valptr = strchr(opt_geninfo, ':');
if (valptr == NULL) {
CMP_err("missing ':' in -geninfo option");
return 0;
}
valptr[0] = '\0';
valptr++;
if (OPENSSL_strncasecmp(valptr, "int:", 4) != 0) {
CMP_err("missing 'int:' in -geninfo option");
return 0;
}
valptr += 4;
value = strtol(valptr, &endstr, 10);
if (endstr == valptr || *endstr != '\0') {
CMP_err("cannot parse int in -geninfo option");
return 0;
}
type = OBJ_txt2obj(opt_geninfo, 1);
if (type == NULL) {
CMP_err("cannot parse OID in -geninfo option");
return 0;
}
if ((aint = ASN1_INTEGER_new()) == NULL)
goto oom;
val = ASN1_TYPE_new();
if (!ASN1_INTEGER_set(aint, value) || val == NULL) {
ASN1_INTEGER_free(aint);
goto oom;
}
ASN1_TYPE_set(val, V_ASN1_INTEGER, aint);
itav = OSSL_CMP_ITAV_create(type, val);
if (itav == NULL) {
ASN1_TYPE_free(val);
goto oom;
}
if (!OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav)) {
OSSL_CMP_ITAV_free(itav);
return 0;
}
return 1;
oom:
ASN1_OBJECT_free(type);
CMP_err("out of memory");
return 0;
}
/*
* set up the client-side OSSL_CMP_CTX based on options from config file/CLI
* while parsing options and checking their consistency.
* Prints reason for error to bio_err.
* Returns 1 on success, 0 on error
*/
static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
{
int ret = 0;
char *host = NULL, *port = NULL, *path = NULL, *used_path = opt_path;
#ifndef OPENSSL_NO_SOCK
int portnum, ssl;
static char server_port[32] = { '\0' };
const char *proxy_host = NULL;
#endif
char server_buf[200] = "mock server";
char proxy_buf[200] = "";
if (!opt_use_mock_srv && opt_rspin == NULL) { /* note: -port is not given */
#ifndef OPENSSL_NO_SOCK
if (opt_server == NULL) {
CMP_err("missing -server or -use_mock_srv or -rspin option");
goto err;
}
#else
CMP_err("missing -use_mock_srv or -rspin option; -server option is not supported due to no-sock build");
goto err;
#endif
}
#ifndef OPENSSL_NO_SOCK
if (opt_server == NULL) {
if (opt_proxy != NULL)
CMP_warn("ignoring -proxy option since -server is not given");
if (opt_no_proxy != NULL)
CMP_warn("ignoring -no_proxy option since -server is not given");
if (opt_tls_used) {
CMP_warn("ignoring -tls_used option since -server is not given");
opt_tls_used = 0;
}
goto set_path;
}
if (!OSSL_HTTP_parse_url(opt_server, &ssl, NULL /* user */, &host, &port,
&portnum, &path, NULL /* q */, NULL /* frag */)) {
CMP_err1("cannot parse -server URL: %s", opt_server);
goto err;
}
if (ssl && !opt_tls_used) {
CMP_err("missing -tls_used option since -server URL indicates https");
goto err;
}
BIO_snprintf(server_port, sizeof(server_port), "%s", port);
if (opt_path == NULL)
used_path = path;
if (!OSSL_CMP_CTX_set1_server(ctx, host)
|| !OSSL_CMP_CTX_set_serverPort(ctx, portnum))
goto oom;
if (opt_proxy != NULL && !OSSL_CMP_CTX_set1_proxy(ctx, opt_proxy))
goto oom;
if (opt_no_proxy != NULL && !OSSL_CMP_CTX_set1_no_proxy(ctx, opt_no_proxy))
goto oom;
(void)BIO_snprintf(server_buf, sizeof(server_buf), "http%s://%s:%s/%s",
opt_tls_used ? "s" : "", host, port,
*used_path == '/' ? used_path + 1 : used_path);
proxy_host = OSSL_HTTP_adapt_proxy(opt_proxy, opt_no_proxy, host, ssl);
if (proxy_host != NULL)
(void)BIO_snprintf(proxy_buf, sizeof(proxy_buf), " via %s", proxy_host);
set_path:
#endif
if (!OSSL_CMP_CTX_set1_serverPath(ctx, used_path))
goto oom;
if (!transform_opts())
goto err;
if (opt_infotype_s != NULL) {
char id_buf[100] = "id-it-";
strncat(id_buf, opt_infotype_s, sizeof(id_buf) - strlen(id_buf) - 1);
if ((opt_infotype = OBJ_sn2nid(id_buf)) == NID_undef) {
CMP_err("unknown OID name in -infotype option");
goto err;
}
}
if (!setup_verification_ctx(ctx))
goto err;
if (opt_keep_alive != 1)
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_KEEP_ALIVE,
opt_keep_alive);
if (opt_total_timeout > 0 && opt_msg_timeout > 0
&& opt_total_timeout < opt_msg_timeout) {
CMP_err2("-total_timeout argument = %d must not be < %d (-msg_timeout)",
opt_total_timeout, opt_msg_timeout);
goto err;
}
if (opt_msg_timeout >= 0) /* must do this before setup_ssl_ctx() */
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_MSG_TIMEOUT,
opt_msg_timeout);
if (opt_total_timeout >= 0)
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_TOTAL_TIMEOUT,
opt_total_timeout);
- if (opt_reqin != NULL && opt_rspin != NULL)
- CMP_warn("-reqin is ignored since -rspin is present");
+ if (opt_rspin != NULL) {
+ rspin_in_use = 1;
+ if (opt_reqin != NULL)
+ CMP_warn("-reqin is ignored since -rspin is present");
+ }
if (opt_reqin_new_tid && opt_reqin == NULL)
CMP_warn("-reqin_new_tid is ignored since -reqin is not present");
if (opt_reqin != NULL || opt_reqout != NULL
|| opt_rspin != NULL || opt_rspout != NULL || opt_use_mock_srv)
(void)OSSL_CMP_CTX_set_transfer_cb(ctx, read_write_req_resp);
#ifndef OPENSSL_NO_SOCK
if (opt_tls_used) {
APP_HTTP_TLS_INFO *info;
if (opt_tls_cert != NULL
|| opt_tls_key != NULL || opt_tls_keypass != NULL) {
if (opt_tls_key == NULL) {
CMP_err("missing -tls_key option");
goto err;
} else if (opt_tls_cert == NULL) {
CMP_err("missing -tls_cert option");
goto err;
}
}
if ((info = OPENSSL_zalloc(sizeof(*info))) == NULL)
goto err;
(void)OSSL_CMP_CTX_set_http_cb_arg(ctx, info);
- info->server = opt_server;
- info->port = server_port;
+ info->ssl_ctx = setup_ssl_ctx(ctx, host, engine);
+ info->server = host;
+ host = NULL; /* prevent deallocation */
+ if ((info->port = OPENSSL_strdup(server_port)) == NULL)
+ goto err;
/* workaround for callback design flaw, see #17088: */
info->use_proxy = proxy_host != NULL;
info->timeout = OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_MSG_TIMEOUT);
- info->ssl_ctx = setup_ssl_ctx(ctx, host, engine);
if (info->ssl_ctx == NULL)
goto err;
(void)OSSL_CMP_CTX_set_http_cb(ctx, app_http_tls_cb);
}
#endif
if (!setup_protection_ctx(ctx, engine))
goto err;
if (!setup_request_ctx(ctx, engine))
goto err;
if (!set_name(opt_recipient, OSSL_CMP_CTX_set1_recipient, ctx, "recipient")
|| !set_name(opt_expect_sender, OSSL_CMP_CTX_set1_expected_sender,
ctx, "expected sender"))
goto err;
if (opt_geninfo != NULL && !handle_opt_geninfo(ctx))
goto err;
/* not printing earlier, to minimize confusion in case setup fails before */
if (opt_rspin != NULL)
- CMP_info("will not contact any server since -rspin is given");
+ CMP_info2("will contact %s%s "
+ "only if -rspin argument gives too few filenames",
+ server_buf, proxy_buf);
else
CMP_info2("will contact %s%s", server_buf, proxy_buf);
ret = 1;
err:
OPENSSL_free(host);
OPENSSL_free(port);
OPENSSL_free(path);
return ret;
oom:
CMP_err("out of memory");
goto err;
}
/*
* write out the given certificate to the output specified by bio.
* Depending on options use either PEM or DER format.
* Returns 1 on success, 0 on error
*/
static int write_cert(BIO *bio, X509 *cert)
{
if ((opt_certform == FORMAT_PEM && PEM_write_bio_X509(bio, cert))
|| (opt_certform == FORMAT_ASN1 && i2d_X509_bio(bio, cert)))
return 1;
if (opt_certform != FORMAT_PEM && opt_certform != FORMAT_ASN1)
BIO_printf(bio_err,
"error: unsupported type '%s' for writing certificates\n",
opt_certform_s);
return 0;
}
/*
* If destFile != NULL writes out a stack of certs to the given file.
* In any case frees the certs.
* Depending on options use either PEM or DER format,
* where DER does not make much sense for writing more than one cert!
* Returns number of written certificates on success, -1 on error.
*/
static int save_free_certs(OSSL_CMP_CTX *ctx,
STACK_OF(X509) *certs, char *destFile, char *desc)
{
BIO *bio = NULL;
int i;
int n = sk_X509_num(certs);
if (destFile == NULL)
goto end;
CMP_info3("received %d %s certificate(s), saving to file '%s'",
n, desc, destFile);
if (n > 1 && opt_certform != FORMAT_PEM)
CMP_warn("saving more than one certificate in non-PEM format");
if (destFile == NULL || (bio = BIO_new(BIO_s_file())) == NULL
|| !BIO_write_filename(bio, (char *)destFile)) {
CMP_err1("could not open file '%s' for writing", destFile);
n = -1;
goto end;
}
for (i = 0; i < n; i++) {
if (!write_cert(bio, sk_X509_value(certs, i))) {
CMP_err1("cannot write certificate to file '%s'", destFile);
n = -1;
goto end;
}
}
end:
BIO_free(bio);
sk_X509_pop_free(certs, X509_free);
return n;
}
static void print_itavs(STACK_OF(OSSL_CMP_ITAV) *itavs)
{
OSSL_CMP_ITAV *itav = NULL;
char buf[128];
int i, r;
int n = sk_OSSL_CMP_ITAV_num(itavs); /* itavs == NULL leads to 0 */
if (n == 0) {
CMP_info("genp contains no ITAV");
return;
}
for (i = 0; i < n; i++) {
itav = sk_OSSL_CMP_ITAV_value(itavs, i);
r = OBJ_obj2txt(buf, 128, OSSL_CMP_ITAV_get0_type(itav), 0);
if (r < 0)
CMP_err("could not get ITAV details");
else if (r == 0)
CMP_info("genp contains empty ITAV");
else
CMP_info1("genp contains ITAV of type: %s", buf);
}
}
static char opt_item[SECTION_NAME_MAX + 1];
/* get previous name from a comma or space-separated list of names */
static const char *prev_item(const char *opt, const char *end)
{
const char *beg;
size_t len;
if (end == opt)
return NULL;
beg = end;
while (beg > opt) {
--beg;
if (beg[0] == ',' || isspace(beg[0])) {
++beg;
break;
}
}
len = end - beg;
if (len > SECTION_NAME_MAX) {
CMP_warn3("using only first %d characters of section name starting with \"%.*s\"",
SECTION_NAME_MAX, SECTION_NAME_MAX, beg);
len = SECTION_NAME_MAX;
}
memcpy(opt_item, beg, len);
opt_item[len] = '\0';
while (beg > opt) {
--beg;
if (beg[0] != ',' && !isspace(beg[0])) {
++beg;
break;
}
}
return beg;
}
/* get str value for name from a comma-separated hierarchy of config sections */
static char *conf_get_string(const CONF *src_conf, const char *groups,
const char *name)
{
char *res = NULL;
const char *end = groups + strlen(groups);
while ((end = prev_item(groups, end)) != NULL) {
if ((res = NCONF_get_string(src_conf, opt_item, name)) != NULL)
return res;
}
return res;
}
/* get long val for name from a comma-separated hierarchy of config sections */
static int conf_get_number_e(const CONF *conf_, const char *groups,
const char *name, long *result)
{
char *str = conf_get_string(conf_, groups, name);
char *tailptr;
long res;
if (str == NULL || *str == '\0')
return 0;
res = strtol(str, &tailptr, 10);
if (res == LONG_MIN || res == LONG_MAX || *tailptr != '\0')
return 0;
*result = res;
return 1;
}
/*
* use the command line option table to read values from the CMP section
* of openssl.cnf. Defaults are taken from the config file, they can be
* overwritten on the command line.
*/
static int read_config(void)
{
unsigned int i;
long num = 0;
char *txt = NULL;
const OPTIONS *opt;
int start_opt = OPT_VERBOSITY - OPT_HELP;
int start_idx = OPT_VERBOSITY - 2;
/*
* starting with offset OPT_VERBOSITY because OPT_CONFIG and OPT_SECTION
* would not make sense within the config file.
*/
int n_options = OSSL_NELEM(cmp_options) - 1;
for (opt = &cmp_options[start_opt], i = start_idx;
opt->name != NULL; i++, opt++)
if (!strcmp(opt->name, OPT_SECTION_STR)
|| !strcmp(opt->name, OPT_MORE_STR))
n_options--;
OPENSSL_assert(OSSL_NELEM(cmp_vars) == n_options
+ OPT_PROV__FIRST + 1 - OPT_PROV__LAST
+ OPT_R__FIRST + 1 - OPT_R__LAST
+ OPT_V__FIRST + 1 - OPT_V__LAST);
for (opt = &cmp_options[start_opt], i = start_idx;
opt->name != NULL; i++, opt++) {
int provider_option = (OPT_PROV__FIRST <= opt->retval
&& opt->retval < OPT_PROV__LAST);
int rand_state_option = (OPT_R__FIRST <= opt->retval
&& opt->retval < OPT_R__LAST);
int verification_option = (OPT_V__FIRST <= opt->retval
&& opt->retval < OPT_V__LAST);
if (strcmp(opt->name, OPT_SECTION_STR) == 0
|| strcmp(opt->name, OPT_MORE_STR) == 0) {
i--;
continue;
}
if (provider_option || rand_state_option || verification_option)
i--;
switch (opt->valtype) {
case '-':
case 'p':
case 'n':
case 'N':
case 'l':
if (!conf_get_number_e(conf, opt_section, opt->name, &num)) {
ERR_clear_error();
continue; /* option not provided */
}
if (opt->valtype == 'p' && num <= 0) {
opt_printf_stderr("Non-positive number \"%ld\" for config option -%s\n",
num, opt->name);
return -1;
}
if (opt->valtype == 'N' && num < 0) {
opt_printf_stderr("Negative number \"%ld\" for config option -%s\n",
num, opt->name);
return -1;
}
break;
case 's':
case '>':
case 'M':
txt = conf_get_string(conf, opt_section, opt->name);
if (txt == NULL) {
ERR_clear_error();
continue; /* option not provided */
}
break;
default:
CMP_err2("internal: unsupported type '%c' for option '%s'",
opt->valtype, opt->name);
return 0;
break;
}
if (provider_option || verification_option) {
int conf_argc = 1;
char *conf_argv[3];
char arg1[82];
BIO_snprintf(arg1, 81, "-%s", (char *)opt->name);
conf_argv[0] = prog;
conf_argv[1] = arg1;
if (opt->valtype == '-') {
if (num != 0)
conf_argc = 2;
} else {
conf_argc = 3;
conf_argv[2] = conf_get_string(conf, opt_section, opt->name);
/* not NULL */
}
if (conf_argc > 1) {
(void)opt_init(conf_argc, conf_argv, cmp_options);
if (provider_option
? !opt_provider(opt_next())
: !opt_verify(opt_next(), vpm)) {
CMP_err2("for option '%s' in config file section '%s'",
opt->name, opt_section);
return 0;
}
}
} else {
switch (opt->valtype) {
case '-':
case 'p':
case 'n':
case 'N':
if (num < INT_MIN || INT_MAX < num) {
BIO_printf(bio_err,
"integer value out of range for option '%s'\n",
opt->name);
return 0;
}
*cmp_vars[i].num = (int)num;
break;
case 'l':
*cmp_vars[i].num_long = num;
break;
default:
if (txt != NULL && txt[0] == '\0')
txt = NULL; /* reset option on empty string input */
*cmp_vars[i].txt = txt;
break;
}
}
}
return 1;
}
static char *opt_str(void)
{
char *arg = opt_arg();
if (arg[0] == '\0') {
CMP_warn1("%s option argument is empty string, resetting option",
opt_flag());
arg = NULL;
} else if (arg[0] == '-') {
CMP_warn1("%s option argument starts with hyphen", opt_flag());
}
return arg;
}
/* returns 1 on success, 0 on error, -1 on -help (i.e., stop with success) */
static int get_opts(int argc, char **argv)
{
OPTION_CHOICE o;
prog = opt_init(argc, argv, cmp_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);
return 0;
case OPT_HELP:
opt_help(cmp_options);
return -1;
case OPT_CONFIG: /* has already been handled */
case OPT_SECTION: /* has already been handled */
break;
case OPT_VERBOSITY:
if (!set_verbosity(opt_int_arg()))
goto opthelp;
break;
#ifndef OPENSSL_NO_SOCK
case OPT_SERVER:
opt_server = opt_str();
break;
case OPT_PROXY:
opt_proxy = opt_str();
break;
case OPT_NO_PROXY:
opt_no_proxy = opt_str();
break;
#endif
case OPT_RECIPIENT:
opt_recipient = opt_str();
break;
case OPT_PATH:
opt_path = opt_str();
break;
case OPT_KEEP_ALIVE:
opt_keep_alive = opt_int_arg();
if (opt_keep_alive > 2) {
CMP_err("-keep_alive argument must be 0, 1, or 2");
goto opthelp;
}
break;
case OPT_MSG_TIMEOUT:
opt_msg_timeout = opt_int_arg();
break;
case OPT_TOTAL_TIMEOUT:
opt_total_timeout = opt_int_arg();
break;
#ifndef OPENSSL_NO_SOCK
case OPT_TLS_USED:
opt_tls_used = 1;
break;
case OPT_TLS_CERT:
opt_tls_cert = opt_str();
break;
case OPT_TLS_KEY:
opt_tls_key = opt_str();
break;
case OPT_TLS_KEYPASS:
opt_tls_keypass = opt_str();
break;
case OPT_TLS_EXTRA:
opt_tls_extra = opt_str();
break;
case OPT_TLS_TRUSTED:
opt_tls_trusted = opt_str();
break;
case OPT_TLS_HOST:
opt_tls_host = opt_str();
break;
#endif
case OPT_REF:
opt_ref = opt_str();
break;
case OPT_SECRET:
opt_secret = opt_str();
break;
case OPT_CERT:
opt_cert = opt_str();
break;
case OPT_OWN_TRUSTED:
opt_own_trusted = opt_str();
break;
case OPT_KEY:
opt_key = opt_str();
break;
case OPT_KEYPASS:
opt_keypass = opt_str();
break;
case OPT_DIGEST:
opt_digest = opt_str();
break;
case OPT_MAC:
opt_mac = opt_str();
break;
case OPT_EXTRACERTS:
opt_extracerts = opt_str();
break;
case OPT_UNPROTECTED_REQUESTS:
opt_unprotected_requests = 1;
break;
case OPT_TRUSTED:
opt_trusted = opt_str();
break;
case OPT_UNTRUSTED:
opt_untrusted = opt_str();
break;
case OPT_SRVCERT:
opt_srvcert = opt_str();
break;
case OPT_EXPECT_SENDER:
opt_expect_sender = opt_str();
break;
case OPT_IGNORE_KEYUSAGE:
opt_ignore_keyusage = 1;
break;
case OPT_UNPROTECTED_ERRORS:
opt_unprotected_errors = 1;
break;
case OPT_EXTRACERTSOUT:
opt_extracertsout = opt_str();
break;
case OPT_CACERTSOUT:
opt_cacertsout = opt_str();
break;
case OPT_V_CASES:
if (!opt_verify(o, vpm))
goto opthelp;
break;
case OPT_CMD:
opt_cmd_s = opt_str();
break;
case OPT_INFOTYPE:
opt_infotype_s = opt_str();
break;
case OPT_GENINFO:
opt_geninfo = opt_str();
break;
case OPT_NEWKEY:
opt_newkey = opt_str();
break;
case OPT_NEWKEYPASS:
opt_newkeypass = opt_str();
break;
case OPT_SUBJECT:
opt_subject = opt_str();
break;
case OPT_ISSUER:
opt_issuer = opt_str();
break;
case OPT_DAYS:
opt_days = opt_int_arg();
break;
case OPT_REQEXTS:
opt_reqexts = opt_str();
break;
case OPT_SANS:
opt_sans = opt_str();
break;
case OPT_SAN_NODEFAULT:
opt_san_nodefault = 1;
break;
case OPT_POLICIES:
opt_policies = opt_str();
break;
case OPT_POLICY_OIDS:
opt_policy_oids = opt_str();
break;
case OPT_POLICY_OIDS_CRITICAL:
opt_policy_oids_critical = 1;
break;
case OPT_POPO:
opt_popo = opt_int_arg();
if (opt_popo < OSSL_CRMF_POPO_NONE
|| opt_popo > OSSL_CRMF_POPO_KEYENC) {
CMP_err("invalid popo spec. Valid values are -1 .. 2");
goto opthelp;
}
break;
case OPT_CSR:
opt_csr = opt_arg();
break;
case OPT_OUT_TRUSTED:
opt_out_trusted = opt_str();
break;
case OPT_IMPLICIT_CONFIRM:
opt_implicit_confirm = 1;
break;
case OPT_DISABLE_CONFIRM:
opt_disable_confirm = 1;
break;
case OPT_CERTOUT:
opt_certout = opt_str();
break;
case OPT_CHAINOUT:
opt_chainout = opt_str();
break;
case OPT_OLDCERT:
opt_oldcert = opt_str();
break;
case OPT_REVREASON:
opt_revreason = opt_int_arg();
if (opt_revreason < CRL_REASON_NONE
|| opt_revreason > CRL_REASON_AA_COMPROMISE
|| opt_revreason == 7) {
CMP_err("invalid revreason. Valid values are -1 .. 6, 8 .. 10");
goto opthelp;
}
break;
case OPT_CERTFORM:
opt_certform_s = opt_str();
break;
case OPT_KEYFORM:
opt_keyform_s = opt_str();
break;
case OPT_OTHERPASS:
opt_otherpass = opt_str();
break;
#ifndef OPENSSL_NO_ENGINE
case OPT_ENGINE:
opt_engine = opt_str();
break;
#endif
case OPT_PROV_CASES:
if (!opt_provider(o))
goto opthelp;
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto opthelp;
break;
case OPT_BATCH:
opt_batch = 1;
break;
case OPT_REPEAT:
opt_repeat = opt_int_arg();
break;
case OPT_REQIN:
opt_reqin = opt_str();
break;
case OPT_REQIN_NEW_TID:
opt_reqin_new_tid = 1;
break;
case OPT_REQOUT:
opt_reqout = opt_str();
break;
case OPT_RSPIN:
opt_rspin = opt_str();
break;
case OPT_RSPOUT:
opt_rspout = opt_str();
break;
case OPT_USE_MOCK_SRV:
opt_use_mock_srv = 1;
break;
#ifndef OPENSSL_NO_SOCK
case OPT_PORT:
opt_port = opt_str();
break;
case OPT_MAX_MSGS:
opt_max_msgs = opt_int_arg();
break;
#endif
case OPT_SRV_REF:
opt_srv_ref = opt_str();
break;
case OPT_SRV_SECRET:
opt_srv_secret = opt_str();
break;
case OPT_SRV_CERT:
opt_srv_cert = opt_str();
break;
case OPT_SRV_KEY:
opt_srv_key = opt_str();
break;
case OPT_SRV_KEYPASS:
opt_srv_keypass = opt_str();
break;
case OPT_SRV_TRUSTED:
opt_srv_trusted = opt_str();
break;
case OPT_SRV_UNTRUSTED:
opt_srv_untrusted = opt_str();
break;
case OPT_RSP_CERT:
opt_rsp_cert = opt_str();
break;
case OPT_RSP_EXTRACERTS:
opt_rsp_extracerts = opt_str();
break;
case OPT_RSP_CAPUBS:
opt_rsp_capubs = opt_str();
break;
case OPT_POLL_COUNT:
opt_poll_count = opt_int_arg();
break;
case OPT_CHECK_AFTER:
opt_check_after = opt_int_arg();
break;
case OPT_GRANT_IMPLICITCONF:
opt_grant_implicitconf = 1;
break;
case OPT_PKISTATUS:
opt_pkistatus = opt_int_arg();
break;
case OPT_FAILURE:
opt_failure = opt_int_arg();
break;
case OPT_FAILUREBITS:
opt_failurebits = opt_int_arg();
break;
case OPT_STATUSSTRING:
opt_statusstring = opt_str();
break;
case OPT_SEND_ERROR:
opt_send_error = 1;
break;
case OPT_SEND_UNPROTECTED:
opt_send_unprotected = 1;
break;
case OPT_SEND_UNPROT_ERR:
opt_send_unprot_err = 1;
break;
case OPT_ACCEPT_UNPROTECTED:
opt_accept_unprotected = 1;
break;
case OPT_ACCEPT_UNPROT_ERR:
opt_accept_unprot_err = 1;
break;
case OPT_ACCEPT_RAVERIFIED:
opt_accept_raverified = 1;
break;
}
}
/* No extra args. */
argc = opt_num_rest();
argv = opt_rest();
if (argc != 0)
goto opthelp;
return 1;
}
#ifndef OPENSSL_NO_SOCK
static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx) {
BIO *acbio;
BIO *cbio = NULL;
int keep_alive = 0;
int msgs = 0;
int retry = 1;
int ret = 1;
if ((acbio = http_server_init_bio(prog, opt_port)) == NULL)
return 0;
while (opt_max_msgs <= 0 || msgs < opt_max_msgs) {
char *path = NULL;
OSSL_CMP_MSG *req = NULL;
OSSL_CMP_MSG *resp = NULL;
ret = http_server_get_asn1_req(ASN1_ITEM_rptr(OSSL_CMP_MSG),
(ASN1_VALUE **)&req, &path,
&cbio, acbio, &keep_alive,
prog, opt_port, 0, 0);
if (ret == 0) { /* no request yet */
if (retry) {
ossl_sleep(1000);
retry = 0;
continue;
}
ret = 0;
goto next;
}
if (ret++ == -1) /* fatal error */
break;
ret = 0;
msgs++;
if (req != NULL) {
if (strcmp(path, "") != 0 && strcmp(path, "pkix/") != 0) {
(void)http_server_send_status(cbio, 404, "Not Found");
CMP_err1("expecting empty path or 'pkix/' but got '%s'",
path);
OPENSSL_free(path);
OSSL_CMP_MSG_free(req);
goto next;
}
OPENSSL_free(path);
resp = OSSL_CMP_CTX_server_perform(cmp_ctx, req);
OSSL_CMP_MSG_free(req);
if (resp == NULL) {
(void)http_server_send_status(cbio,
500, "Internal Server Error");
break; /* treated as fatal error */
}
ret = http_server_send_asn1_resp(cbio, keep_alive,
"application/pkixcmp",
ASN1_ITEM_rptr(OSSL_CMP_MSG),
(const ASN1_VALUE *)resp);
OSSL_CMP_MSG_free(resp);
if (!ret)
break; /* treated as fatal error */
}
next:
if (!ret) { /* on transmission error, cancel CMP transaction */
(void)OSSL_CMP_CTX_set1_transactionID(srv_cmp_ctx, NULL);
(void)OSSL_CMP_CTX_set1_senderNonce(srv_cmp_ctx, NULL);
}
if (!ret || !keep_alive
|| OSSL_CMP_CTX_get_status(srv_cmp_ctx) != OSSL_CMP_PKISTATUS_trans
/* transaction closed by OSSL_CMP_CTX_server_perform() */) {
BIO_free_all(cbio);
cbio = NULL;
}
}
BIO_free_all(cbio);
BIO_free_all(acbio);
return ret;
}
#endif
static void print_status(void)
{
/* print PKIStatusInfo */
int status = OSSL_CMP_CTX_get_status(cmp_ctx);
char *buf = app_malloc(OSSL_CMP_PKISI_BUFLEN, "PKIStatusInfo buf");
const char *string =
OSSL_CMP_CTX_snprint_PKIStatus(cmp_ctx, buf, OSSL_CMP_PKISI_BUFLEN);
const char *from = "", *server = "";
#ifndef OPENSSL_NO_SOCK
if (opt_server != NULL) {
from = " from ";
server = opt_server;
}
#endif
CMP_print(bio_err,
status == OSSL_CMP_PKISTATUS_accepted
? OSSL_CMP_LOG_INFO :
status == OSSL_CMP_PKISTATUS_rejection
|| status == OSSL_CMP_PKISTATUS_waiting
? OSSL_CMP_LOG_ERR : OSSL_CMP_LOG_WARNING,
status == OSSL_CMP_PKISTATUS_accepted ? "info" :
status == OSSL_CMP_PKISTATUS_rejection ? "server error" :
status == OSSL_CMP_PKISTATUS_waiting ? "internal error"
: "warning", "received%s%s %s", from, server,
string != NULL ? string : "<unknown PKIStatus>");
OPENSSL_free(buf);
}
int cmp_main(int argc, char **argv)
{
char *configfile = NULL;
int i;
X509 *newcert = NULL;
ENGINE *engine = NULL;
OSSL_CMP_CTX *srv_cmp_ctx = NULL;
int ret = 0; /* default: failure */
prog = opt_appname(argv[0]);
if (argc <= 1) {
opt_help(cmp_options);
goto err;
}
/*
* handle options -config, -section, and -verbosity upfront
* to take effect for other options
*/
for (i = 1; i < argc - 1; i++) {
if (*argv[i] == '-') {
if (!strcmp(argv[i] + 1, cmp_options[OPT_CONFIG - OPT_HELP].name))
opt_config = argv[++i];
else if (!strcmp(argv[i] + 1,
cmp_options[OPT_SECTION - OPT_HELP].name))
opt_section = argv[++i];
else if (strcmp(argv[i] + 1,
cmp_options[OPT_VERBOSITY - OPT_HELP].name) == 0
&& !set_verbosity(atoi(argv[++i])))
goto err;
}
}
if (opt_section[0] == '\0') /* empty string */
opt_section = DEFAULT_SECTION;
vpm = X509_VERIFY_PARAM_new();
if (vpm == NULL) {
CMP_err("out of memory");
goto err;
}
/* read default values for options from config file */
configfile = opt_config != NULL ? opt_config : default_config_file;
if (configfile != NULL && configfile[0] != '\0' /* non-empty string */
&& (configfile != default_config_file || access(configfile, F_OK) != -1)) {
CMP_info2("using section(s) '%s' of OpenSSL configuration file '%s'",
opt_section, configfile);
conf = app_load_config(configfile);
if (conf == NULL) {
goto err;
} else {
if (strcmp(opt_section, CMP_SECTION) == 0) { /* default */
if (!NCONF_get_section(conf, opt_section))
CMP_info2("no [%s] section found in config file '%s';"
" will thus use just [default] and unnamed section if present",
opt_section, configfile);
} else {
const char *end = opt_section + strlen(opt_section);
while ((end = prev_item(opt_section, end)) != NULL) {
if (!NCONF_get_section(conf, opt_item)) {
CMP_err2("no [%s] section found in config file '%s'",
opt_item, configfile);
goto err;
}
}
}
ret = read_config();
if (!set_verbosity(opt_verbosity)) /* just for checking range */
ret = -1;
if (ret <= 0) {
if (ret == -1)
BIO_printf(bio_err, "Use -help for summary.\n");
goto err;
}
}
}
(void)BIO_flush(bio_err); /* prevent interference with opt_help() */
ret = get_opts(argc, argv);
if (ret <= 0)
goto err;
ret = 0;
if (!app_RAND_load())
goto err;
if (opt_batch)
set_base_ui_method(UI_null());
if (opt_engine != NULL) {
engine = setup_engine_methods(opt_engine, 0 /* not: ENGINE_METHOD_ALL */, 0);
if (engine == NULL) {
CMP_err1("cannot load engine %s", opt_engine);
goto err;
}
}
cmp_ctx = OSSL_CMP_CTX_new(app_get0_libctx(), app_get0_propq());
if (cmp_ctx == NULL)
goto err;
OSSL_CMP_CTX_set_log_verbosity(cmp_ctx, opt_verbosity);
if (!OSSL_CMP_CTX_set_log_cb(cmp_ctx, print_to_bio_out)) {
CMP_err1("cannot set up error reporting and logging for %s", prog);
goto err;
}
#ifndef OPENSSL_NO_SOCK
if ((opt_tls_cert != NULL || opt_tls_key != NULL
|| opt_tls_keypass != NULL || opt_tls_extra != NULL
|| opt_tls_trusted != NULL || opt_tls_host != NULL)
&& !opt_tls_used)
CMP_warn("Ingnoring TLS options(s) since -tls_used is not given");
if (opt_port != NULL) {
if (opt_tls_used) {
CMP_err("-tls_used option not supported with -port option");
goto err;
}
- if (opt_use_mock_srv || opt_server != NULL || opt_rspin != NULL) {
- CMP_err("cannot use -port with -use_mock_srv, -server, or -rspin options");
+ if (opt_server != NULL || opt_use_mock_srv) {
+ CMP_err("The -port option excludes -server and -use_mock_srv");
+ goto err;
+ }
+ if (opt_reqin != NULL || opt_reqout != NULL) {
+ CMP_err("The -port option does not support -reqin and -reqout");
+ goto err;
+ }
+ if (opt_rspin != NULL || opt_rspout != NULL) {
+ CMP_err("The -port option does not support -rspin and -rspout");
goto err;
}
}
if (opt_server != NULL && opt_use_mock_srv) {
CMP_err("cannot use both -server and -use_mock_srv options");
goto err;
}
#endif
- if (opt_rspin != NULL && opt_use_mock_srv) {
- CMP_err("cannot use both -rspin and -use_mock_srv options");
- goto err;
- }
if (opt_use_mock_srv
#ifndef OPENSSL_NO_SOCK
|| opt_port != NULL
#endif
) {
OSSL_CMP_SRV_CTX *srv_ctx;
if ((srv_ctx = setup_srv_ctx(engine)) == NULL)
goto err;
srv_cmp_ctx = OSSL_CMP_SRV_CTX_get0_cmp_ctx(srv_ctx);
OSSL_CMP_CTX_set_transfer_cb_arg(cmp_ctx, srv_ctx);
if (!OSSL_CMP_CTX_set_log_cb(srv_cmp_ctx, print_to_bio_err)) {
CMP_err1("cannot set up error reporting and logging for %s", prog);
goto err;
}
OSSL_CMP_CTX_set_log_verbosity(srv_cmp_ctx, opt_verbosity);
}
#ifndef OPENSSL_NO_SOCK
- if (opt_tls_used && (opt_use_mock_srv || opt_rspin != NULL)) {
- CMP_warn("ignoring -tls_used option since -use_mock_srv or -rspin is given");
+ if (opt_tls_used && (opt_use_mock_srv || opt_server == NULL)) {
+ CMP_warn("ignoring -tls_used option since -use_mock_srv is given or -server is not given");
opt_tls_used = 0;
}
if (opt_port != NULL) { /* act as very basic CMP HTTP server */
ret = cmp_server(srv_cmp_ctx);
goto err;
}
/* act as CMP client, possibly using internal mock server */
- if (opt_server != NULL) {
- if (opt_rspin != NULL) {
- CMP_warn("ignoring -server option since -rspin is given");
- opt_server = NULL;
- }
+ if (opt_rspin != NULL) {
+ if (opt_server != NULL)
+ CMP_warn("-server option is not used if enough filenames given for -rspin");
+ if (opt_use_mock_srv)
+ CMP_warn("-use_mock_srv option is not used if enough filenames given for -rspin");
}
#endif
if (!setup_client_ctx(cmp_ctx, engine)) {
CMP_err("cannot set up CMP context");
goto err;
}
for (i = 0; i < opt_repeat; i++) {
/* everything is ready, now connect and perform the command! */
switch (opt_cmd) {
case CMP_IR:
newcert = OSSL_CMP_exec_IR_ses(cmp_ctx);
if (newcert != NULL)
ret = 1;
break;
case CMP_KUR:
newcert = OSSL_CMP_exec_KUR_ses(cmp_ctx);
if (newcert != NULL)
ret = 1;
break;
case CMP_CR:
newcert = OSSL_CMP_exec_CR_ses(cmp_ctx);
if (newcert != NULL)
ret = 1;
break;
case CMP_P10CR:
newcert = OSSL_CMP_exec_P10CR_ses(cmp_ctx);
if (newcert != NULL)
ret = 1;
break;
case CMP_RR:
ret = OSSL_CMP_exec_RR_ses(cmp_ctx);
break;
case CMP_GENM:
{
STACK_OF(OSSL_CMP_ITAV) *itavs;
if (opt_infotype != NID_undef) {
OSSL_CMP_ITAV *itav =
OSSL_CMP_ITAV_create(OBJ_nid2obj(opt_infotype), NULL);
if (itav == NULL)
goto err;
OSSL_CMP_CTX_push0_genm_ITAV(cmp_ctx, itav);
}
if ((itavs = OSSL_CMP_exec_GENM_ses(cmp_ctx)) != NULL) {
print_itavs(itavs);
sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
ret = 1;
}
break;
}
default:
break;
}
if (OSSL_CMP_CTX_get_status(cmp_ctx) < OSSL_CMP_PKISTATUS_accepted)
goto err; /* we got no response, maybe even did not send request */
print_status();
if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_extraCertsIn(cmp_ctx),
opt_extracertsout, "extra") < 0)
ret = 0;
if (!ret)
goto err;
ret = 0;
if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_caPubs(cmp_ctx),
opt_cacertsout, "CA") < 0)
goto err;
if (newcert != NULL) {
STACK_OF(X509) *certs = sk_X509_new_null();
if (!X509_add_cert(certs, newcert, X509_ADD_FLAG_UP_REF)) {
sk_X509_free(certs);
goto err;
}
if (save_free_certs(cmp_ctx, certs, opt_certout, "enrolled") < 0)
goto err;
}
if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_newChain(cmp_ctx),
opt_chainout, "chain") < 0)
goto err;
if (!OSSL_CMP_CTX_reinit(cmp_ctx))
goto err;
}
ret = 1;
err:
/* in case we ended up here on error without proper cleaning */
cleanse(opt_keypass);
cleanse(opt_newkeypass);
cleanse(opt_otherpass);
#ifndef OPENSSL_NO_SOCK
cleanse(opt_tls_keypass);
#endif
cleanse(opt_secret);
cleanse(opt_srv_keypass);
cleanse(opt_srv_secret);
if (ret != 1)
OSSL_CMP_CTX_print_errors(cmp_ctx);
if (cmp_ctx != NULL) {
#ifndef OPENSSL_NO_SOCK
APP_HTTP_TLS_INFO *info = OSSL_CMP_CTX_get_http_cb_arg(cmp_ctx);
#endif
ossl_cmp_mock_srv_free(OSSL_CMP_CTX_get_transfer_cb_arg(cmp_ctx));
X509_STORE_free(OSSL_CMP_CTX_get_certConf_cb_arg(cmp_ctx));
/* cannot free info already here, as it may be used indirectly by: */
OSSL_CMP_CTX_free(cmp_ctx);
#ifndef OPENSSL_NO_SOCK
- APP_HTTP_TLS_INFO_free(info);
+ if (info != NULL) {
+ OPENSSL_free((char *)info->server);
+ OPENSSL_free((char *)info->port);
+ APP_HTTP_TLS_INFO_free(info);
+ }
#endif
}
X509_VERIFY_PARAM_free(vpm);
release_engine(engine);
NCONF_free(conf); /* must not do as long as opt_... variables are used */
OSSL_CMP_log_close();
return ret == 0 ? EXIT_FAILURE : EXIT_SUCCESS; /* ret == -1 for -help */
}
diff --git a/apps/dgst.c b/apps/dgst.c
index 1042d940f49c..e12389197de4 100644
--- a/apps/dgst.c
+++ b/apps/dgst.c
@@ -1,652 +1,655 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <string.h>
#include <stdlib.h>
#include "apps.h"
#include "progs.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/hmac.h>
#include <ctype.h>
#undef BUFSIZE
#define BUFSIZE 1024*8
int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen,
EVP_PKEY *key, unsigned char *sigin, int siglen,
const char *sig_name, const char *md_name,
const char *file);
static void show_digests(const OBJ_NAME *name, void *bio_);
struct doall_dgst_digests {
BIO *bio;
int n;
};
typedef enum OPTION_choice {
OPT_COMMON,
OPT_LIST,
OPT_C, OPT_R, OPT_OUT, OPT_SIGN, OPT_PASSIN, OPT_VERIFY,
OPT_PRVERIFY, OPT_SIGNATURE, OPT_KEYFORM, OPT_ENGINE, OPT_ENGINE_IMPL,
OPT_HEX, OPT_BINARY, OPT_DEBUG, OPT_FIPS_FINGERPRINT,
OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT, OPT_XOFLEN,
OPT_DIGEST,
OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS dgst_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] [file...]\n"},
OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"list", OPT_LIST, '-', "List digests"},
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
{"engine_impl", OPT_ENGINE_IMPL, '-',
"Also use engine given by -engine for digest operations"},
#endif
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
OPT_SECTION("Output"),
{"c", OPT_C, '-', "Print the digest with separating colons"},
{"r", OPT_R, '-', "Print the digest in coreutils format"},
{"out", OPT_OUT, '>', "Output to filename rather than stdout"},
{"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"},
{"hex", OPT_HEX, '-', "Print as hex dump"},
{"binary", OPT_BINARY, '-', "Print in binary form"},
{"xoflen", OPT_XOFLEN, 'p', "Output length for XOF algorithms. To obtain the maximum security strength set this to 32 (or greater) for SHAKE128, and 64 (or greater) for SHAKE256"},
{"d", OPT_DEBUG, '-', "Print debug info"},
{"debug", OPT_DEBUG, '-', "Print debug info"},
OPT_SECTION("Signing"),
{"sign", OPT_SIGN, 's', "Sign digest using private key"},
{"verify", OPT_VERIFY, 's', "Verify a signature using public key"},
{"prverify", OPT_PRVERIFY, 's', "Verify a signature using private key"},
{"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
{"signature", OPT_SIGNATURE, '<', "File with signature to verify"},
{"hmac", OPT_HMAC, 's', "Create hashed MAC with key"},
{"mac", OPT_MAC, 's', "Create MAC (not necessarily HMAC)"},
{"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form or key"},
{"", OPT_DIGEST, '-', "Any supported digest"},
{"fips-fingerprint", OPT_FIPS_FINGERPRINT, '-',
"Compute HMAC with the key used in OpenSSL-FIPS fingerprint"},
OPT_R_OPTIONS,
OPT_PROV_OPTIONS,
OPT_PARAMETERS(),
{"file", 0, 0, "Files to digest (optional; default is stdin)"},
{NULL}
};
int dgst_main(int argc, char **argv)
{
BIO *in = NULL, *inp, *bmd = NULL, *out = NULL;
ENGINE *e = NULL, *impl = NULL;
EVP_PKEY *sigkey = NULL;
STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL;
char *hmac_key = NULL;
char *mac_name = NULL, *digestname = NULL;
char *passinarg = NULL, *passin = NULL;
EVP_MD *md = NULL;
const char *outfile = NULL, *keyfile = NULL, *prog = NULL;
const char *sigfile = NULL;
const char *md_name = NULL;
OPTION_CHOICE o;
int separator = 0, debug = 0, keyform = FORMAT_UNDEF, siglen = 0;
int i, ret = EXIT_FAILURE, out_bin = -1, want_pub = 0, do_verify = 0;
int xoflen = 0;
unsigned char *buf = NULL, *sigbuf = NULL;
int engine_impl = 0;
struct doall_dgst_digests dec;
buf = app_malloc(BUFSIZE, "I/O buffer");
md = (EVP_MD *)EVP_get_digestbyname(argv[0]);
if (md != NULL)
digestname = argv[0];
prog = opt_init(argc, argv, dgst_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(dgst_options);
ret = EXIT_SUCCESS;
goto end;
case OPT_LIST:
BIO_printf(bio_out, "Supported digests:\n");
dec.bio = bio_out;
dec.n = 0;
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH,
show_digests, &dec);
BIO_printf(bio_out, "\n");
ret = EXIT_SUCCESS;
goto end;
case OPT_C:
separator = 1;
break;
case OPT_R:
separator = 2;
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
case OPT_OUT:
outfile = opt_arg();
break;
case OPT_SIGN:
keyfile = opt_arg();
break;
case OPT_PASSIN:
passinarg = opt_arg();
break;
case OPT_VERIFY:
keyfile = opt_arg();
want_pub = do_verify = 1;
break;
case OPT_PRVERIFY:
keyfile = opt_arg();
do_verify = 1;
break;
case OPT_SIGNATURE:
sigfile = opt_arg();
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
goto opthelp;
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
case OPT_ENGINE_IMPL:
engine_impl = 1;
break;
case OPT_HEX:
out_bin = 0;
break;
case OPT_BINARY:
out_bin = 1;
break;
case OPT_XOFLEN:
xoflen = atoi(opt_arg());
break;
case OPT_DEBUG:
debug = 1;
break;
case OPT_FIPS_FINGERPRINT:
hmac_key = "etaonrishdlcupfm";
break;
case OPT_HMAC:
hmac_key = opt_arg();
break;
case OPT_MAC:
mac_name = opt_arg();
break;
case OPT_SIGOPT:
if (!sigopts)
sigopts = sk_OPENSSL_STRING_new_null();
if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
goto opthelp;
break;
case OPT_MACOPT:
if (!macopts)
macopts = sk_OPENSSL_STRING_new_null();
if (!macopts || !sk_OPENSSL_STRING_push(macopts, opt_arg()))
goto opthelp;
break;
case OPT_DIGEST:
digestname = opt_unknown();
break;
case OPT_PROV_CASES:
if (!opt_provider(o))
goto end;
break;
}
}
/* Remaining args are files to digest. */
argc = opt_num_rest();
argv = opt_rest();
if (keyfile != NULL && argc > 1) {
BIO_printf(bio_err, "%s: Can only sign or verify one file.\n", prog);
goto end;
}
if (!app_RAND_load())
goto end;
if (digestname != NULL) {
if (!opt_md(digestname, &md))
goto opthelp;
}
if (do_verify && sigfile == NULL) {
BIO_printf(bio_err,
"No signature to verify: use the -signature option\n");
goto end;
}
if (engine_impl)
impl = e;
in = BIO_new(BIO_s_file());
bmd = BIO_new(BIO_f_md());
if (in == NULL || bmd == NULL)
goto end;
if (debug) {
BIO_set_callback_ex(in, BIO_debug_callback_ex);
/* needed for windows 3.1 */
BIO_set_callback_arg(in, (char *)bio_err);
}
if (!app_passwd(passinarg, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
if (out_bin == -1) {
if (keyfile != NULL)
out_bin = 1;
else
out_bin = 0;
}
out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT);
if (out == NULL)
goto end;
if ((!(mac_name == NULL) + !(keyfile == NULL) + !(hmac_key == NULL)) > 1) {
BIO_printf(bio_err, "MAC and signing key cannot both be specified\n");
goto end;
}
if (keyfile != NULL) {
int type;
if (want_pub)
sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key");
else
sigkey = load_key(keyfile, keyform, 0, passin, e, "private key");
if (sigkey == NULL) {
/*
* load_[pub]key() has already printed an appropriate message
*/
goto end;
}
type = EVP_PKEY_get_id(sigkey);
if (type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448) {
/*
* We implement PureEdDSA for these which doesn't have a separate
* digest, and only supports one shot.
*/
BIO_printf(bio_err, "Key type not supported for this operation\n");
goto end;
}
}
if (mac_name != NULL) {
EVP_PKEY_CTX *mac_ctx = NULL;
if (!init_gen_str(&mac_ctx, mac_name, impl, 0, NULL, NULL))
goto end;
if (macopts != NULL) {
for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) {
char *macopt = sk_OPENSSL_STRING_value(macopts, i);
if (pkey_ctrl_string(mac_ctx, macopt) <= 0) {
EVP_PKEY_CTX_free(mac_ctx);
BIO_printf(bio_err, "MAC parameter error \"%s\"\n", macopt);
goto end;
}
}
}
sigkey = app_keygen(mac_ctx, mac_name, 0, 0 /* not verbose */);
/* Verbose output would make external-tests gost-engine fail */
EVP_PKEY_CTX_free(mac_ctx);
}
if (hmac_key != NULL) {
if (md == NULL) {
md = (EVP_MD *)EVP_sha256();
digestname = SN_sha256;
}
sigkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, impl,
(unsigned char *)hmac_key,
strlen(hmac_key));
if (sigkey == NULL)
goto end;
}
if (sigkey != NULL) {
EVP_MD_CTX *mctx = NULL;
EVP_PKEY_CTX *pctx = NULL;
int res;
if (BIO_get_md_ctx(bmd, &mctx) <= 0) {
BIO_printf(bio_err, "Error getting context\n");
goto end;
}
if (do_verify)
if (impl == NULL)
res = EVP_DigestVerifyInit_ex(mctx, &pctx, digestname,
app_get0_libctx(),
app_get0_propq(), sigkey, NULL);
else
res = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey);
else
if (impl == NULL)
res = EVP_DigestSignInit_ex(mctx, &pctx, digestname,
app_get0_libctx(),
app_get0_propq(), sigkey, NULL);
else
res = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey);
if (res == 0) {
BIO_printf(bio_err, "Error setting context\n");
goto end;
}
if (sigopts != NULL) {
for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
if (pkey_ctrl_string(pctx, sigopt) <= 0) {
BIO_printf(bio_err, "Signature parameter error \"%s\"\n",
sigopt);
goto end;
}
}
}
}
/* we use md as a filter, reading from 'in' */
else {
EVP_MD_CTX *mctx = NULL;
if (BIO_get_md_ctx(bmd, &mctx) <= 0) {
BIO_printf(bio_err, "Error getting context\n");
goto end;
}
if (md == NULL)
md = (EVP_MD *)EVP_sha256();
if (!EVP_DigestInit_ex(mctx, md, impl)) {
BIO_printf(bio_err, "Error setting digest\n");
goto end;
}
}
if (sigfile != NULL && sigkey != NULL) {
BIO *sigbio = BIO_new_file(sigfile, "rb");
if (sigbio == NULL) {
BIO_printf(bio_err, "Error opening signature file %s\n", sigfile);
goto end;
}
siglen = EVP_PKEY_get_size(sigkey);
sigbuf = app_malloc(siglen, "signature buffer");
siglen = BIO_read(sigbio, sigbuf, siglen);
BIO_free(sigbio);
if (siglen <= 0) {
BIO_printf(bio_err, "Error reading signature file %s\n", sigfile);
goto end;
}
}
inp = BIO_push(bmd, in);
if (md == NULL) {
EVP_MD_CTX *tctx;
BIO_get_md_ctx(bmd, &tctx);
md = EVP_MD_CTX_get1_md(tctx);
}
if (md != NULL)
md_name = EVP_MD_get0_name(md);
if (xoflen > 0) {
if (!(EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF)) {
BIO_printf(bio_err, "Length can only be specified for XOF\n");
goto end;
}
/*
* Signing using XOF is not supported by any algorithms currently since
* each algorithm only calls EVP_DigestFinal_ex() in their sign_final
* and verify_final methods.
*/
if (sigkey != NULL) {
BIO_printf(bio_err, "Signing key cannot be specified for XOF\n");
goto end;
}
}
if (argc == 0) {
BIO_set_fp(in, stdin, BIO_NOCLOSE);
ret = do_fp(out, buf, inp, separator, out_bin, xoflen, sigkey, sigbuf,
siglen, NULL, md_name, "stdin");
} else {
const char *sig_name = NULL;
if (out_bin == 0) {
if (sigkey != NULL)
sig_name = EVP_PKEY_get0_type_name(sigkey);
}
ret = EXIT_SUCCESS;
for (i = 0; i < argc; i++) {
if (BIO_read_filename(in, argv[i]) <= 0) {
perror(argv[i]);
ret = EXIT_FAILURE;
continue;
} else {
if (do_fp(out, buf, inp, separator, out_bin, xoflen,
sigkey, sigbuf, siglen, sig_name, md_name, argv[i]))
ret = EXIT_FAILURE;
}
(void)BIO_reset(bmd);
}
}
end:
if (ret != EXIT_SUCCESS)
ERR_print_errors(bio_err);
OPENSSL_clear_free(buf, BUFSIZE);
BIO_free(in);
OPENSSL_free(passin);
BIO_free_all(out);
EVP_MD_free(md);
EVP_PKEY_free(sigkey);
sk_OPENSSL_STRING_free(sigopts);
sk_OPENSSL_STRING_free(macopts);
OPENSSL_free(sigbuf);
BIO_free(bmd);
release_engine(e);
return ret;
}
static void show_digests(const OBJ_NAME *name, void *arg)
{
struct doall_dgst_digests *dec = (struct doall_dgst_digests *)arg;
const EVP_MD *md = NULL;
/* Filter out signed digests (a.k.a signature algorithms) */
if (strstr(name->name, "rsa") != NULL || strstr(name->name, "RSA") != NULL)
return;
if (!islower((unsigned char)*name->name))
return;
/* Filter out message digests that we cannot use */
md = EVP_MD_fetch(app_get0_libctx(), name->name, app_get0_propq());
- if (md == NULL)
- return;
+ if (md == NULL) {
+ md = EVP_get_digestbyname(name->name);
+ if (md == NULL)
+ return;
+ }
BIO_printf(dec->bio, "-%-25s", name->name);
if (++dec->n == 3) {
BIO_printf(dec->bio, "\n");
dec->n = 0;
} else {
BIO_printf(dec->bio, " ");
}
}
/*
* The newline_escape_filename function performs newline escaping for any
* filename that contains a newline. This function also takes a pointer
* to backslash. The backslash pointer is a flag to indicating whether a newline
* is present in the filename. If a newline is present, the backslash flag is
* set and the output format will contain a backslash at the beginning of the
* digest output. This output format is to replicate the output format found
* in the '*sum' checksum programs. This aims to preserve backward
* compatibility.
*/
static const char *newline_escape_filename(const char *file, int * backslash)
{
size_t i, e = 0, length = strlen(file), newline_count = 0, mem_len = 0;
char *file_cpy = NULL;
for (i = 0; i < length; i++)
if (file[i] == '\n')
newline_count++;
mem_len = length + newline_count + 1;
file_cpy = app_malloc(mem_len, file);
i = 0;
while(e < length) {
const char c = file[e];
if (c == '\n') {
file_cpy[i++] = '\\';
file_cpy[i++] = 'n';
*backslash = 1;
} else {
file_cpy[i++] = c;
}
e++;
}
file_cpy[i] = '\0';
return (const char*)file_cpy;
}
int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen,
EVP_PKEY *key, unsigned char *sigin, int siglen,
const char *sig_name, const char *md_name,
const char *file)
{
size_t len = BUFSIZE;
int i, backslash = 0, ret = EXIT_FAILURE;
unsigned char *allocated_buf = NULL;
while (BIO_pending(bp) || !BIO_eof(bp)) {
i = BIO_read(bp, (char *)buf, BUFSIZE);
if (i < 0) {
BIO_printf(bio_err, "Read error in %s\n", file);
goto end;
}
if (i == 0)
break;
}
if (sigin != NULL) {
EVP_MD_CTX *ctx;
BIO_get_md_ctx(bp, &ctx);
i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen);
if (i > 0) {
BIO_printf(out, "Verified OK\n");
} else if (i == 0) {
BIO_printf(out, "Verification failure\n");
goto end;
} else {
BIO_printf(bio_err, "Error verifying data\n");
goto end;
}
ret = EXIT_SUCCESS;
goto end;
}
if (key != NULL) {
EVP_MD_CTX *ctx;
size_t tmplen;
BIO_get_md_ctx(bp, &ctx);
if (!EVP_DigestSignFinal(ctx, NULL, &tmplen)) {
BIO_printf(bio_err, "Error getting maximum length of signed data\n");
goto end;
}
if (tmplen > BUFSIZE) {
len = tmplen;
allocated_buf = app_malloc(len, "Signature buffer");
buf = allocated_buf;
}
if (!EVP_DigestSignFinal(ctx, buf, &len)) {
BIO_printf(bio_err, "Error signing data\n");
goto end;
}
} else if (xoflen > 0) {
EVP_MD_CTX *ctx;
len = xoflen;
if (len > BUFSIZE) {
allocated_buf = app_malloc(len, "Digest buffer");
buf = allocated_buf;
}
BIO_get_md_ctx(bp, &ctx);
if (!EVP_DigestFinalXOF(ctx, buf, len)) {
BIO_printf(bio_err, "Error Digesting Data\n");
goto end;
}
} else {
len = BIO_gets(bp, (char *)buf, BUFSIZE);
if ((int)len < 0)
goto end;
}
if (binout) {
BIO_write(out, buf, len);
} else if (sep == 2) {
file = newline_escape_filename(file, &backslash);
if (backslash == 1)
BIO_puts(out, "\\");
for (i = 0; i < (int)len; i++)
BIO_printf(out, "%02x", buf[i]);
BIO_printf(out, " *%s\n", file);
OPENSSL_free((char *)file);
} else {
if (sig_name != NULL) {
BIO_puts(out, sig_name);
if (md_name != NULL)
BIO_printf(out, "-%s", md_name);
BIO_printf(out, "(%s)= ", file);
} else if (md_name != NULL) {
BIO_printf(out, "%s(%s)= ", md_name, file);
} else {
BIO_printf(out, "(%s)= ", file);
}
for (i = 0; i < (int)len; i++) {
if (sep && (i != 0))
BIO_printf(out, ":");
BIO_printf(out, "%02x", buf[i]);
}
BIO_printf(out, "\n");
}
ret = EXIT_SUCCESS;
end:
if (allocated_buf != NULL)
OPENSSL_clear_free(allocated_buf, len);
return ret;
}
diff --git a/apps/enc.c b/apps/enc.c
index 3dd609856304..b3bf4cc2592d 100644
--- a/apps/enc.c
+++ b/apps/enc.c
@@ -1,696 +1,705 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <stdlib.h>
#include <string.h>
#include <limits.h>
#include "apps.h"
#include "progs.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/rand.h>
#include <openssl/pem.h>
#ifndef OPENSSL_NO_COMP
# include <openssl/comp.h>
#endif
#include <ctype.h>
#undef SIZE
#undef BSIZE
#define SIZE (512)
#define BSIZE (8*1024)
+#define PBKDF2_ITER_DEFAULT 10000
+#define STR(a) XSTR(a)
+#define XSTR(a) #a
+
static int set_hex(const char *in, unsigned char *out, int size);
static void show_ciphers(const OBJ_NAME *name, void *bio_);
struct doall_enc_ciphers {
BIO *bio;
int n;
};
typedef enum OPTION_choice {
OPT_COMMON,
OPT_LIST,
OPT_E, OPT_IN, OPT_OUT, OPT_PASS, OPT_ENGINE, OPT_D, OPT_P, OPT_V,
OPT_NOPAD, OPT_SALT, OPT_NOSALT, OPT_DEBUG, OPT_UPPER_P, OPT_UPPER_A,
OPT_A, OPT_Z, OPT_BUFSIZE, OPT_K, OPT_KFILE, OPT_UPPER_K, OPT_NONE,
OPT_UPPER_S, OPT_IV, OPT_MD, OPT_ITER, OPT_PBKDF2, OPT_CIPHER,
OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS enc_options[] = {
OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"list", OPT_LIST, '-', "List ciphers"},
#ifndef OPENSSL_NO_DEPRECATED_3_0
{"ciphers", OPT_LIST, '-', "Alias for -list"},
#endif
{"e", OPT_E, '-', "Encrypt"},
{"d", OPT_D, '-', "Decrypt"},
{"p", OPT_P, '-', "Print the iv/key"},
{"P", OPT_UPPER_P, '-', "Print the iv/key and exit"},
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file"},
{"k", OPT_K, 's', "Passphrase"},
{"kfile", OPT_KFILE, '<', "Read passphrase from file"},
OPT_SECTION("Output"),
{"out", OPT_OUT, '>', "Output file"},
{"pass", OPT_PASS, 's', "Passphrase source"},
{"v", OPT_V, '-', "Verbose output"},
{"a", OPT_A, '-', "Base64 encode/decode, depending on encryption flag"},
{"base64", OPT_A, '-', "Same as option -a"},
{"A", OPT_UPPER_A, '-',
"Used with -[base64|a] to specify base64 buffer as a single line"},
OPT_SECTION("Encryption"),
{"nopad", OPT_NOPAD, '-', "Disable standard block padding"},
{"salt", OPT_SALT, '-', "Use salt in the KDF (default)"},
{"nosalt", OPT_NOSALT, '-', "Do not use salt in the KDF"},
{"debug", OPT_DEBUG, '-', "Print debug info"},
{"bufsize", OPT_BUFSIZE, 's', "Buffer size"},
{"K", OPT_UPPER_K, 's', "Raw key, in hex"},
{"S", OPT_UPPER_S, 's', "Salt, in hex"},
{"iv", OPT_IV, 's', "IV in hex"},
{"md", OPT_MD, 's', "Use specified digest to create a key from the passphrase"},
- {"iter", OPT_ITER, 'p', "Specify the iteration count and force use of PBKDF2"},
- {"pbkdf2", OPT_PBKDF2, '-', "Use password-based key derivation function 2"},
+ {"iter", OPT_ITER, 'p',
+ "Specify the iteration count and force the use of PBKDF2"},
+ {OPT_MORE_STR, 0, 0, "Default: " STR(PBKDF2_ITER_DEFAULT)},
+ {"pbkdf2", OPT_PBKDF2, '-',
+ "Use password-based key derivation function 2 (PBKDF2)"},
+ {OPT_MORE_STR, 0, 0,
+ "Use -iter to change the iteration count from " STR(PBKDF2_ITER_DEFAULT)},
{"none", OPT_NONE, '-', "Don't encrypt"},
#ifdef ZLIB
{"z", OPT_Z, '-', "Compress or decompress encrypted data using zlib"},
#endif
{"", OPT_CIPHER, '-', "Any supported cipher"},
OPT_R_OPTIONS,
OPT_PROV_OPTIONS,
{NULL}
};
int enc_main(int argc, char **argv)
{
static char buf[128];
static const char magic[] = "Salted__";
ENGINE *e = NULL;
BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL, *rbio =
NULL, *wbio = NULL;
EVP_CIPHER_CTX *ctx = NULL;
EVP_CIPHER *cipher = NULL;
EVP_MD *dgst = NULL;
const char *digestname = NULL;
char *hkey = NULL, *hiv = NULL, *hsalt = NULL, *p;
char *infile = NULL, *outfile = NULL, *prog;
char *str = NULL, *passarg = NULL, *pass = NULL, *strbuf = NULL;
const char *ciphername = NULL;
char mbuf[sizeof(magic) - 1];
OPTION_CHOICE o;
int bsize = BSIZE, verbose = 0, debug = 0, olb64 = 0, nosalt = 0;
int enc = 1, printkey = 0, i, k;
int base64 = 0, informat = FORMAT_BINARY, outformat = FORMAT_BINARY;
int ret = 1, inl, nopad = 0;
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
unsigned char *buff = NULL, salt[PKCS5_SALT_LEN];
int pbkdf2 = 0;
int iter = 0;
long n;
struct doall_enc_ciphers dec;
#ifdef ZLIB
int do_zlib = 0;
BIO *bzl = NULL;
#endif
/* first check the command name */
if (strcmp(argv[0], "base64") == 0)
base64 = 1;
#ifdef ZLIB
else if (strcmp(argv[0], "zlib") == 0)
do_zlib = 1;
#endif
else if (strcmp(argv[0], "enc") != 0)
ciphername = argv[0];
prog = opt_init(argc, argv, enc_options);
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
case OPT_ERR:
opthelp:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
opt_help(enc_options);
ret = 0;
goto end;
case OPT_LIST:
BIO_printf(bio_out, "Supported ciphers:\n");
dec.bio = bio_out;
dec.n = 0;
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
show_ciphers, &dec);
BIO_printf(bio_out, "\n");
ret = 0;
goto end;
case OPT_E:
enc = 1;
break;
case OPT_IN:
infile = opt_arg();
break;
case OPT_OUT:
outfile = opt_arg();
break;
case OPT_PASS:
passarg = opt_arg();
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
case OPT_D:
enc = 0;
break;
case OPT_P:
printkey = 1;
break;
case OPT_V:
verbose = 1;
break;
case OPT_NOPAD:
nopad = 1;
break;
case OPT_SALT:
nosalt = 0;
break;
case OPT_NOSALT:
nosalt = 1;
break;
case OPT_DEBUG:
debug = 1;
break;
case OPT_UPPER_P:
printkey = 2;
break;
case OPT_UPPER_A:
olb64 = 1;
break;
case OPT_A:
base64 = 1;
break;
case OPT_Z:
#ifdef ZLIB
do_zlib = 1;
#endif
break;
case OPT_BUFSIZE:
p = opt_arg();
i = (int)strlen(p) - 1;
k = i >= 1 && p[i] == 'k';
if (k)
p[i] = '\0';
if (!opt_long(opt_arg(), &n)
|| n < 0 || (k && n >= LONG_MAX / 1024))
goto opthelp;
if (k)
n *= 1024;
bsize = (int)n;
break;
case OPT_K:
str = opt_arg();
break;
case OPT_KFILE:
in = bio_open_default(opt_arg(), 'r', FORMAT_TEXT);
if (in == NULL)
goto opthelp;
i = BIO_gets(in, buf, sizeof(buf));
BIO_free(in);
in = NULL;
if (i <= 0) {
BIO_printf(bio_err,
"%s Can't read key from %s\n", prog, opt_arg());
goto opthelp;
}
while (--i > 0 && (buf[i] == '\r' || buf[i] == '\n'))
buf[i] = '\0';
if (i <= 0) {
BIO_printf(bio_err, "%s: zero length password\n", prog);
goto opthelp;
}
str = buf;
break;
case OPT_UPPER_K:
hkey = opt_arg();
break;
case OPT_UPPER_S:
hsalt = opt_arg();
break;
case OPT_IV:
hiv = opt_arg();
break;
case OPT_MD:
digestname = opt_arg();
break;
case OPT_CIPHER:
ciphername = opt_unknown();
break;
case OPT_ITER:
iter = opt_int_arg();
pbkdf2 = 1;
break;
case OPT_PBKDF2:
pbkdf2 = 1;
if (iter == 0) /* do not overwrite a chosen value */
- iter = 10000;
+ iter = PBKDF2_ITER_DEFAULT;
break;
case OPT_NONE:
cipher = NULL;
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
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;
/* Get the cipher name, either from progname (if set) or flag. */
if (ciphername != NULL) {
if (!opt_cipher(ciphername, &cipher))
goto opthelp;
}
if (digestname != NULL) {
if (!opt_md(digestname, &dgst))
goto opthelp;
}
if (dgst == NULL)
dgst = (EVP_MD *)EVP_sha256();
if (iter == 0)
iter = 1;
/* It must be large enough for a base64 encoded line */
if (base64 && bsize < 80)
bsize = 80;
if (verbose)
BIO_printf(bio_err, "bufsize=%d\n", bsize);
#ifdef ZLIB
if (!do_zlib)
#endif
if (base64) {
if (enc)
outformat = FORMAT_BASE64;
else
informat = FORMAT_BASE64;
}
strbuf = app_malloc(SIZE, "strbuf");
buff = app_malloc(EVP_ENCODE_LENGTH(bsize), "evp buffer");
if (infile == NULL) {
in = dup_bio_in(informat);
} else {
in = bio_open_default(infile, 'r', informat);
}
if (in == NULL)
goto end;
if (str == NULL && passarg != NULL) {
if (!app_passwd(passarg, NULL, &pass, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
str = pass;
}
if ((str == NULL) && (cipher != NULL) && (hkey == NULL)) {
if (1) {
#ifndef OPENSSL_NO_UI_CONSOLE
for (;;) {
char prompt[200];
BIO_snprintf(prompt, sizeof(prompt), "enter %s %s password:",
EVP_CIPHER_get0_name(cipher),
(enc) ? "encryption" : "decryption");
strbuf[0] = '\0';
i = EVP_read_pw_string((char *)strbuf, SIZE, prompt, enc);
if (i == 0) {
if (strbuf[0] == '\0') {
ret = 1;
goto end;
}
str = strbuf;
break;
}
if (i < 0) {
BIO_printf(bio_err, "bad password read\n");
goto end;
}
}
} else {
#endif
BIO_printf(bio_err, "password required\n");
goto end;
}
}
out = bio_open_default(outfile, 'w', outformat);
if (out == NULL)
goto end;
if (debug) {
BIO_set_callback_ex(in, BIO_debug_callback_ex);
BIO_set_callback_ex(out, BIO_debug_callback_ex);
BIO_set_callback_arg(in, (char *)bio_err);
BIO_set_callback_arg(out, (char *)bio_err);
}
rbio = in;
wbio = out;
#ifdef ZLIB
if (do_zlib) {
if ((bzl = BIO_new(BIO_f_zlib())) == NULL)
goto end;
if (debug) {
BIO_set_callback_ex(bzl, BIO_debug_callback_ex);
BIO_set_callback_arg(bzl, (char *)bio_err);
}
if (enc)
wbio = BIO_push(bzl, wbio);
else
rbio = BIO_push(bzl, rbio);
}
#endif
if (base64) {
if ((b64 = BIO_new(BIO_f_base64())) == NULL)
goto end;
if (debug) {
BIO_set_callback_ex(b64, BIO_debug_callback_ex);
BIO_set_callback_arg(b64, (char *)bio_err);
}
if (olb64)
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
if (enc)
wbio = BIO_push(b64, wbio);
else
rbio = BIO_push(b64, rbio);
}
if (cipher != NULL) {
if (str != NULL) { /* a passphrase is available */
/*
* Salt handling: if encrypting generate a salt if not supplied,
* and write to output BIO. If decrypting use salt from input BIO
* if not given with args
*/
unsigned char *sptr;
size_t str_len = strlen(str);
if (nosalt) {
sptr = NULL;
} else {
if (hsalt != NULL && !set_hex(hsalt, salt, sizeof(salt))) {
BIO_printf(bio_err, "invalid hex salt value\n");
goto end;
}
if (enc) { /* encryption */
if (hsalt == NULL) {
if (RAND_bytes(salt, sizeof(salt)) <= 0) {
BIO_printf(bio_err, "RAND_bytes failed\n");
goto end;
}
/*
* If -P option then don't bother writing.
* If salt is given, shouldn't either ?
*/
if ((printkey != 2)
&& (BIO_write(wbio, magic,
sizeof(magic) - 1) != sizeof(magic) - 1
|| BIO_write(wbio,
(char *)salt,
sizeof(salt)) != sizeof(salt))) {
BIO_printf(bio_err, "error writing output file\n");
goto end;
}
}
} else { /* decryption */
if (hsalt == NULL) {
if (BIO_read(rbio, mbuf, sizeof(mbuf)) != sizeof(mbuf)) {
BIO_printf(bio_err, "error reading input file\n");
goto end;
}
if (memcmp(mbuf, magic, sizeof(mbuf)) == 0) { /* file IS salted */
if (BIO_read(rbio, salt,
sizeof(salt)) != sizeof(salt)) {
BIO_printf(bio_err, "error reading input file\n");
goto end;
}
} else { /* file is NOT salted, NO salt available */
BIO_printf(bio_err, "bad magic number\n");
goto end;
}
}
}
sptr = salt;
}
if (pbkdf2 == 1) {
/*
* derive key and default iv
* concatenated into a temporary buffer
*/
unsigned char tmpkeyiv[EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH];
int iklen = EVP_CIPHER_get_key_length(cipher);
int ivlen = EVP_CIPHER_get_iv_length(cipher);
/* not needed if HASH_UPDATE() is fixed : */
int islen = (sptr != NULL ? sizeof(salt) : 0);
if (!PKCS5_PBKDF2_HMAC(str, str_len, sptr, islen,
iter, dgst, iklen+ivlen, tmpkeyiv)) {
BIO_printf(bio_err, "PKCS5_PBKDF2_HMAC failed\n");
goto end;
}
/* split and move data back to global buffer */
memcpy(key, tmpkeyiv, iklen);
memcpy(iv, tmpkeyiv+iklen, ivlen);
} else {
BIO_printf(bio_err, "*** WARNING : "
"deprecated key derivation used.\n"
"Using -iter or -pbkdf2 would be better.\n");
if (!EVP_BytesToKey(cipher, dgst, sptr,
(unsigned char *)str, str_len,
1, key, iv)) {
BIO_printf(bio_err, "EVP_BytesToKey failed\n");
goto end;
}
}
/*
* zero the complete buffer or the string passed from the command
* line.
*/
if (str == strbuf)
OPENSSL_cleanse(str, SIZE);
else
OPENSSL_cleanse(str, str_len);
}
if (hiv != NULL) {
int siz = EVP_CIPHER_get_iv_length(cipher);
if (siz == 0) {
BIO_printf(bio_err, "warning: iv not used by this cipher\n");
} else if (!set_hex(hiv, iv, siz)) {
BIO_printf(bio_err, "invalid hex iv value\n");
goto end;
}
}
if ((hiv == NULL) && (str == NULL)
&& EVP_CIPHER_get_iv_length(cipher) != 0) {
/*
* No IV was explicitly set and no IV was generated.
* Hence the IV is undefined, making correct decryption impossible.
*/
BIO_printf(bio_err, "iv undefined\n");
goto end;
}
if (hkey != NULL) {
if (!set_hex(hkey, key, EVP_CIPHER_get_key_length(cipher))) {
BIO_printf(bio_err, "invalid hex key value\n");
goto end;
}
/* wiping secret data as we no longer need it */
cleanse(hkey);
}
if ((benc = BIO_new(BIO_f_cipher())) == NULL)
goto end;
/*
* Since we may be changing parameters work on the encryption context
* rather than calling BIO_set_cipher().
*/
BIO_get_cipher_ctx(benc, &ctx);
if (!EVP_CipherInit_ex(ctx, cipher, e, NULL, NULL, enc)) {
BIO_printf(bio_err, "Error setting cipher %s\n",
EVP_CIPHER_get0_name(cipher));
ERR_print_errors(bio_err);
goto end;
}
if (nopad)
EVP_CIPHER_CTX_set_padding(ctx, 0);
if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc)) {
BIO_printf(bio_err, "Error setting cipher %s\n",
EVP_CIPHER_get0_name(cipher));
ERR_print_errors(bio_err);
goto end;
}
if (debug) {
BIO_set_callback_ex(benc, BIO_debug_callback_ex);
BIO_set_callback_arg(benc, (char *)bio_err);
}
if (printkey) {
if (!nosalt) {
printf("salt=");
for (i = 0; i < (int)sizeof(salt); i++)
printf("%02X", salt[i]);
printf("\n");
}
if (EVP_CIPHER_get_key_length(cipher) > 0) {
printf("key=");
for (i = 0; i < EVP_CIPHER_get_key_length(cipher); i++)
printf("%02X", key[i]);
printf("\n");
}
if (EVP_CIPHER_get_iv_length(cipher) > 0) {
printf("iv =");
for (i = 0; i < EVP_CIPHER_get_iv_length(cipher); i++)
printf("%02X", iv[i]);
printf("\n");
}
if (printkey == 2) {
ret = 0;
goto end;
}
}
}
/* Only encrypt/decrypt as we write the file */
if (benc != NULL)
wbio = BIO_push(benc, wbio);
while (BIO_pending(rbio) || !BIO_eof(rbio)) {
inl = BIO_read(rbio, (char *)buff, bsize);
if (inl <= 0)
break;
if (BIO_write(wbio, (char *)buff, inl) != inl) {
BIO_printf(bio_err, "error writing output file\n");
goto end;
}
}
if (!BIO_flush(wbio)) {
BIO_printf(bio_err, "bad decrypt\n");
goto end;
}
ret = 0;
if (verbose) {
BIO_printf(bio_err, "bytes read : %8ju\n", BIO_number_read(in));
BIO_printf(bio_err, "bytes written: %8ju\n", BIO_number_written(out));
}
end:
ERR_print_errors(bio_err);
OPENSSL_free(strbuf);
OPENSSL_free(buff);
BIO_free(in);
BIO_free_all(out);
BIO_free(benc);
BIO_free(b64);
EVP_MD_free(dgst);
EVP_CIPHER_free(cipher);
#ifdef ZLIB
BIO_free(bzl);
#endif
release_engine(e);
OPENSSL_free(pass);
return ret;
}
static void show_ciphers(const OBJ_NAME *name, void *arg)
{
struct doall_enc_ciphers *dec = (struct doall_enc_ciphers *)arg;
const EVP_CIPHER *cipher;
if (!islower((unsigned char)*name->name))
return;
/* Filter out ciphers that we cannot use */
cipher = EVP_get_cipherbyname(name->name);
if (cipher == NULL
|| (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0
|| EVP_CIPHER_get_mode(cipher) == EVP_CIPH_XTS_MODE)
return;
BIO_printf(dec->bio, "-%-25s", name->name);
if (++dec->n == 3) {
BIO_printf(dec->bio, "\n");
dec->n = 0;
} else
BIO_printf(dec->bio, " ");
}
static int set_hex(const char *in, unsigned char *out, int size)
{
int i, n;
unsigned char j;
i = size * 2;
n = strlen(in);
if (n > i) {
BIO_printf(bio_err, "hex string is too long, ignoring excess\n");
n = i; /* ignore exceeding part */
} else if (n < i) {
BIO_printf(bio_err, "hex string is too short, padding with zero bytes to length\n");
}
memset(out, 0, size);
for (i = 0; i < n; i++) {
j = (unsigned char)*in++;
if (!isxdigit(j)) {
BIO_printf(bio_err, "non-hex digit\n");
return 0;
}
j = (unsigned char)OPENSSL_hexchar2int(j);
if (i & 1)
out[i / 2] |= j;
else
out[i / 2] = (j << 4);
}
return 1;
}
diff --git a/apps/include/cmp_mock_srv.h b/apps/include/cmp_mock_srv.h
index 6beba1473590..18c141c563c4 100644
--- a/apps/include/cmp_mock_srv.h
+++ b/apps/include/cmp_mock_srv.h
@@ -1,35 +1,35 @@
/*
- * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-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
*/
#ifndef OSSL_APPS_CMP_MOCK_SRV_H
# define OSSL_APPS_CMP_MOCK_SRV_H
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_CMP
# include <openssl/cmp.h>
OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx,
const char *propq);
void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx);
int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
STACK_OF(X509) *chain);
int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
STACK_OF(X509) *caPubs);
int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
int fail_info, const char *text);
-int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val);
+int ossl_cmp_mock_srv_set_sendError(OSSL_CMP_SRV_CTX *srv_ctx, int bodytype);
int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count);
int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec);
# endif /* !defined(OPENSSL_NO_CMP) */
#endif /* !defined(OSSL_APPS_CMP_MOCK_SRV_H) */
diff --git a/apps/lib/apps.c b/apps/lib/apps.c
index 0d7a20b52afc..79afa1deab99 100644
--- a/apps/lib/apps.c
+++ b/apps/lib/apps.c
@@ -1,3389 +1,3393 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
#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
#ifndef OPENSSL_NO_ENGINE
/* We need to use some deprecated APIs */
# define OPENSSL_SUPPRESS_DEPRECATED
# include <openssl/engine.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifndef OPENSSL_NO_POSIX_IO
# include <sys/stat.h>
# include <fcntl.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/http.h>
#include <openssl/pem.h>
#include <openssl/store.h>
#include <openssl/pkcs12.h>
#include <openssl/ui.h>
#include <openssl/safestack.h>
#include <openssl/rsa.h>
#include <openssl/rand.h>
#include <openssl/bn.h>
#include <openssl/ssl.h>
#include <openssl/store.h>
#include <openssl/core_names.h>
#include "s_apps.h"
#include "apps.h"
#ifdef _WIN32
static int WIN32_rename(const char *from, const char *to);
# define rename(from,to) WIN32_rename((from),(to))
#endif
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
# include <conio.h>
#endif
#if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) || defined(__BORLANDC__)
# define _kbhit kbhit
#endif
static BIO *bio_open_default_(const char *filename, char mode, int format,
int quiet);
#define PASS_SOURCE_SIZE_MAX 4
DEFINE_STACK_OF(CONF)
typedef struct {
const char *name;
unsigned long flag;
unsigned long mask;
} NAME_EX_TBL;
static int set_table_opts(unsigned long *flags, const char *arg,
const NAME_EX_TBL * in_tbl);
static int set_multi_opts(unsigned long *flags, const char *arg,
const NAME_EX_TBL * in_tbl);
static
int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin,
const char *pass, const char *desc,
EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
EVP_PKEY **pparams,
X509 **pcert, STACK_OF(X509) **pcerts,
X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls,
int suppress_decode_errors);
int app_init(long mesgwin);
int chopup_args(ARGS *arg, char *buf)
{
int quoted;
char c = '\0', *p = NULL;
arg->argc = 0;
if (arg->size == 0) {
arg->size = 20;
arg->argv = app_malloc(sizeof(*arg->argv) * arg->size, "argv space");
}
for (p = buf;;) {
/* Skip whitespace. */
while (*p && isspace(_UC(*p)))
p++;
if (*p == '\0')
break;
/* The start of something good :-) */
if (arg->argc >= arg->size) {
char **tmp;
arg->size += 20;
tmp = OPENSSL_realloc(arg->argv, sizeof(*arg->argv) * arg->size);
if (tmp == NULL)
return 0;
arg->argv = tmp;
}
quoted = *p == '\'' || *p == '"';
if (quoted)
c = *p++;
arg->argv[arg->argc++] = p;
/* now look for the end of this */
if (quoted) {
while (*p && *p != c)
p++;
*p++ = '\0';
} else {
while (*p && !isspace(_UC(*p)))
p++;
if (*p)
*p++ = '\0';
}
}
arg->argv[arg->argc] = NULL;
return 1;
}
#ifndef APP_INIT
int app_init(long mesgwin)
{
return 1;
}
#endif
int ctx_set_verify_locations(SSL_CTX *ctx,
const char *CAfile, int noCAfile,
const char *CApath, int noCApath,
const char *CAstore, int noCAstore)
{
if (CAfile == NULL && CApath == NULL && CAstore == NULL) {
if (!noCAfile && SSL_CTX_set_default_verify_file(ctx) <= 0)
return 0;
if (!noCApath && SSL_CTX_set_default_verify_dir(ctx) <= 0)
return 0;
if (!noCAstore && SSL_CTX_set_default_verify_store(ctx) <= 0)
return 0;
return 1;
}
if (CAfile != NULL && !SSL_CTX_load_verify_file(ctx, CAfile))
return 0;
if (CApath != NULL && !SSL_CTX_load_verify_dir(ctx, CApath))
return 0;
if (CAstore != NULL && !SSL_CTX_load_verify_store(ctx, CAstore))
return 0;
return 1;
}
#ifndef OPENSSL_NO_CT
int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path)
{
if (path == NULL)
return SSL_CTX_set_default_ctlog_list_file(ctx);
return SSL_CTX_set_ctlog_list_file(ctx, path);
}
#endif
static unsigned long nmflag = 0;
static char nmflag_set = 0;
int set_nameopt(const char *arg)
{
int ret = set_name_ex(&nmflag, arg);
if (ret)
nmflag_set = 1;
return ret;
}
unsigned long get_nameopt(void)
{
return (nmflag_set) ? nmflag : XN_FLAG_ONELINE;
}
void dump_cert_text(BIO *out, X509 *x)
{
print_name(out, "subject=", X509_get_subject_name(x));
print_name(out, "issuer=", X509_get_issuer_name(x));
}
int wrap_password_callback(char *buf, int bufsiz, int verify, void *userdata)
{
return password_callback(buf, bufsiz, verify, (PW_CB_DATA *)userdata);
}
static char *app_get_pass(const char *arg, int keepbio);
char *get_passwd(const char *pass, const char *desc)
{
char *result = NULL;
if (desc == NULL)
desc = "<unknown>";
if (!app_passwd(pass, NULL, &result, NULL))
BIO_printf(bio_err, "Error getting password for %s\n", desc);
if (pass != NULL && result == NULL) {
BIO_printf(bio_err,
"Trying plain input string (better precede with 'pass:')\n");
result = OPENSSL_strdup(pass);
if (result == NULL)
BIO_printf(bio_err, "Out of memory getting password for %s\n", desc);
}
return result;
}
int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2)
{
int same = arg1 != NULL && arg2 != NULL && strcmp(arg1, arg2) == 0;
if (arg1 != NULL) {
*pass1 = app_get_pass(arg1, same);
if (*pass1 == NULL)
return 0;
} else if (pass1 != NULL) {
*pass1 = NULL;
}
if (arg2 != NULL) {
*pass2 = app_get_pass(arg2, same ? 2 : 0);
if (*pass2 == NULL)
return 0;
} else if (pass2 != NULL) {
*pass2 = NULL;
}
return 1;
}
static char *app_get_pass(const char *arg, int keepbio)
{
static BIO *pwdbio = NULL;
char *tmp, tpass[APP_PASS_LEN];
int i;
/* PASS_SOURCE_SIZE_MAX = max number of chars before ':' in below strings */
if (strncmp(arg, "pass:", 5) == 0)
return OPENSSL_strdup(arg + 5);
if (strncmp(arg, "env:", 4) == 0) {
tmp = getenv(arg + 4);
if (tmp == NULL) {
BIO_printf(bio_err, "No environment variable %s\n", arg + 4);
return NULL;
}
return OPENSSL_strdup(tmp);
}
if (!keepbio || pwdbio == NULL) {
if (strncmp(arg, "file:", 5) == 0) {
pwdbio = BIO_new_file(arg + 5, "r");
if (pwdbio == NULL) {
BIO_printf(bio_err, "Can't open file %s\n", arg + 5);
return NULL;
}
#if !defined(_WIN32)
/*
* Under _WIN32, which covers even Win64 and CE, file
* descriptors referenced by BIO_s_fd are not inherited
* by child process and therefore below is not an option.
* It could have been an option if bss_fd.c was operating
* on real Windows descriptors, such as those obtained
* with CreateFile.
*/
} else if (strncmp(arg, "fd:", 3) == 0) {
BIO *btmp;
i = atoi(arg + 3);
if (i >= 0)
pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
if ((i < 0) || pwdbio == NULL) {
BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3);
return NULL;
}
/*
* Can't do BIO_gets on an fd BIO so add a buffering BIO
*/
btmp = BIO_new(BIO_f_buffer());
if (btmp == NULL) {
BIO_free_all(pwdbio);
pwdbio = NULL;
BIO_printf(bio_err, "Out of memory\n");
return NULL;
}
pwdbio = BIO_push(btmp, pwdbio);
#endif
} else if (strcmp(arg, "stdin") == 0) {
unbuffer(stdin);
pwdbio = dup_bio_in(FORMAT_TEXT);
if (pwdbio == NULL) {
BIO_printf(bio_err, "Can't open BIO for stdin\n");
return NULL;
}
} else {
/* argument syntax error; do not reveal too much about arg */
tmp = strchr(arg, ':');
if (tmp == NULL || tmp - arg > PASS_SOURCE_SIZE_MAX)
BIO_printf(bio_err,
"Invalid password argument, missing ':' within the first %d chars\n",
PASS_SOURCE_SIZE_MAX + 1);
else
BIO_printf(bio_err,
"Invalid password argument, starting with \"%.*s\"\n",
(int)(tmp - arg + 1), arg);
return NULL;
}
}
i = BIO_gets(pwdbio, tpass, APP_PASS_LEN);
if (keepbio != 1) {
BIO_free_all(pwdbio);
pwdbio = NULL;
}
if (i <= 0) {
BIO_printf(bio_err, "Error reading password from BIO\n");
return NULL;
}
tmp = strchr(tpass, '\n');
if (tmp != NULL)
*tmp = 0;
return OPENSSL_strdup(tpass);
}
CONF *app_load_config_bio(BIO *in, const char *filename)
{
long errorline = -1;
CONF *conf;
int i;
conf = NCONF_new_ex(app_get0_libctx(), NULL);
i = NCONF_load_bio(conf, in, &errorline);
if (i > 0)
return conf;
if (errorline <= 0) {
BIO_printf(bio_err, "%s: Can't load ", opt_getprog());
} else {
BIO_printf(bio_err, "%s: Error on line %ld of ", opt_getprog(),
errorline);
}
if (filename != NULL)
BIO_printf(bio_err, "config file \"%s\"\n", filename);
else
BIO_printf(bio_err, "config input");
NCONF_free(conf);
return NULL;
}
CONF *app_load_config_verbose(const char *filename, int verbose)
{
if (verbose) {
if (*filename == '\0')
BIO_printf(bio_err, "No configuration used\n");
else
BIO_printf(bio_err, "Using configuration from %s\n", filename);
}
return app_load_config_internal(filename, 0);
}
CONF *app_load_config_internal(const char *filename, int quiet)
{
BIO *in;
CONF *conf;
if (filename == NULL || *filename != '\0') {
if ((in = bio_open_default_(filename, 'r', FORMAT_TEXT, quiet)) == NULL)
return NULL;
conf = app_load_config_bio(in, filename);
BIO_free(in);
} else {
/* Return empty config if filename is empty string. */
conf = NCONF_new_ex(app_get0_libctx(), NULL);
}
return conf;
}
int app_load_modules(const CONF *config)
{
CONF *to_free = NULL;
if (config == NULL)
config = to_free = app_load_config_quiet(default_config_file);
if (config == NULL)
return 1;
if (CONF_modules_load(config, NULL, 0) <= 0) {
BIO_printf(bio_err, "Error configuring OpenSSL modules\n");
ERR_print_errors(bio_err);
NCONF_free(to_free);
return 0;
}
NCONF_free(to_free);
return 1;
}
int add_oid_section(CONF *conf)
{
char *p;
STACK_OF(CONF_VALUE) *sktmp;
CONF_VALUE *cnf;
int i;
if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) {
ERR_clear_error();
return 1;
}
if ((sktmp = NCONF_get_section(conf, p)) == NULL) {
BIO_printf(bio_err, "problem loading oid section %s\n", p);
return 0;
}
for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
cnf = sk_CONF_VALUE_value(sktmp, i);
if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
BIO_printf(bio_err, "problem creating object %s=%s\n",
cnf->name, cnf->value);
return 0;
}
}
return 1;
}
CONF *app_load_config_modules(const char *configfile)
{
CONF *conf = NULL;
if (configfile != NULL) {
if ((conf = app_load_config_verbose(configfile, 1)) == NULL)
return NULL;
if (configfile != default_config_file && !app_load_modules(conf)) {
NCONF_free(conf);
conf = NULL;
}
}
return conf;
}
#define IS_HTTP(uri) ((uri) != NULL \
&& strncmp(uri, OSSL_HTTP_PREFIX, strlen(OSSL_HTTP_PREFIX)) == 0)
#define IS_HTTPS(uri) ((uri) != NULL \
&& strncmp(uri, OSSL_HTTPS_PREFIX, strlen(OSSL_HTTPS_PREFIX)) == 0)
X509 *load_cert_pass(const char *uri, int format, int maybe_stdin,
const char *pass, const char *desc)
{
X509 *cert = NULL;
if (desc == NULL)
desc = "certificate";
if (IS_HTTPS(uri))
BIO_printf(bio_err, "Loading %s over HTTPS is unsupported\n", desc);
else if (IS_HTTP(uri))
cert = X509_load_http(uri, NULL, NULL, 0 /* timeout */);
else
(void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc,
NULL, NULL, NULL, &cert, NULL, NULL, NULL);
if (cert == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
}
return cert;
}
X509_CRL *load_crl(const char *uri, int format, int maybe_stdin,
const char *desc)
{
X509_CRL *crl = NULL;
if (desc == NULL)
desc = "CRL";
if (IS_HTTPS(uri))
BIO_printf(bio_err, "Loading %s over HTTPS is unsupported\n", desc);
else if (IS_HTTP(uri))
crl = X509_CRL_load_http(uri, NULL, NULL, 0 /* timeout */);
else
(void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc,
NULL, NULL, NULL, NULL, NULL, &crl, NULL);
if (crl == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
}
return crl;
}
X509_REQ *load_csr(const char *file, int format, const char *desc)
{
X509_REQ *req = NULL;
BIO *in;
if (format == FORMAT_UNDEF)
format = FORMAT_PEM;
if (desc == NULL)
desc = "CSR";
in = bio_open_default(file, 'r', format);
if (in == NULL)
goto end;
if (format == FORMAT_ASN1)
req = d2i_X509_REQ_bio(in, NULL);
else if (format == FORMAT_PEM)
req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
else
print_format_error(format, OPT_FMT_PEMDER);
end:
if (req == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
}
BIO_free(in);
return req;
}
void cleanse(char *str)
{
if (str != NULL)
OPENSSL_cleanse(str, strlen(str));
}
void clear_free(char *str)
{
if (str != NULL)
OPENSSL_clear_free(str, strlen(str));
}
EVP_PKEY *load_key(const char *uri, int format, int may_stdin,
const char *pass, ENGINE *e, const char *desc)
{
EVP_PKEY *pkey = NULL;
char *allocated_uri = NULL;
if (desc == NULL)
desc = "private key";
if (format == FORMAT_ENGINE) {
uri = allocated_uri = make_engine_uri(e, uri, desc);
}
(void)load_key_certs_crls(uri, format, may_stdin, pass, desc,
&pkey, NULL, NULL, NULL, NULL, NULL, NULL);
OPENSSL_free(allocated_uri);
return pkey;
}
EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
const char *pass, ENGINE *e, const char *desc)
{
EVP_PKEY *pkey = NULL;
char *allocated_uri = NULL;
if (desc == NULL)
desc = "public key";
if (format == FORMAT_ENGINE) {
uri = allocated_uri = make_engine_uri(e, uri, desc);
}
(void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc,
NULL, &pkey, NULL, NULL, NULL, NULL, NULL);
OPENSSL_free(allocated_uri);
return pkey;
}
EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin,
const char *keytype, const char *desc,
int suppress_decode_errors)
{
EVP_PKEY *params = NULL;
if (desc == NULL)
desc = "key parameters";
(void)load_key_certs_crls_suppress(uri, format, maybe_stdin, NULL, desc,
NULL, NULL, &params, NULL, NULL, NULL,
NULL, suppress_decode_errors);
if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) {
if (!suppress_decode_errors) {
BIO_printf(bio_err,
"Unable to load %s from %s (unexpected parameters type)\n",
desc, uri);
ERR_print_errors(bio_err);
}
EVP_PKEY_free(params);
params = NULL;
}
return params;
}
EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin,
const char *keytype, const char *desc)
{
return load_keyparams_suppress(uri, format, maybe_stdin, keytype, desc, 0);
}
void app_bail_out(char *fmt, ...)
{
va_list args;
va_start(args, fmt);
BIO_vprintf(bio_err, fmt, args);
va_end(args);
ERR_print_errors(bio_err);
exit(EXIT_FAILURE);
}
void *app_malloc(size_t sz, const char *what)
{
void *vp = OPENSSL_malloc(sz);
if (vp == NULL)
app_bail_out("%s: Could not allocate %zu bytes for %s\n",
opt_getprog(), sz, what);
return vp;
}
char *next_item(char *opt) /* in list separated by comma and/or space */
{
/* advance to separator (comma or whitespace), if any */
while (*opt != ',' && !isspace(*opt) && *opt != '\0')
opt++;
if (*opt != '\0') {
/* terminate current item */
*opt++ = '\0';
/* skip over any whitespace after separator */
while (isspace(*opt))
opt++;
}
return *opt == '\0' ? NULL : opt; /* NULL indicates end of input */
}
static void warn_cert_msg(const char *uri, X509 *cert, const char *msg)
{
char *subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
BIO_printf(bio_err, "Warning: certificate from '%s' with subject '%s' %s\n",
uri, subj, msg);
OPENSSL_free(subj);
}
static void warn_cert(const char *uri, X509 *cert, int warn_EE,
X509_VERIFY_PARAM *vpm)
{
uint32_t ex_flags = X509_get_extension_flags(cert);
int res = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert),
X509_get0_notAfter(cert));
if (res != 0)
warn_cert_msg(uri, cert, res > 0 ? "has expired" : "not yet valid");
if (warn_EE && (ex_flags & EXFLAG_V1) == 0 && (ex_flags & EXFLAG_CA) == 0)
warn_cert_msg(uri, cert, "is not a CA cert");
}
static void warn_certs(const char *uri, STACK_OF(X509) *certs, int warn_EE,
X509_VERIFY_PARAM *vpm)
{
int i;
for (i = 0; i < sk_X509_num(certs); i++)
warn_cert(uri, sk_X509_value(certs, i), warn_EE, vpm);
}
int load_cert_certs(const char *uri,
X509 **pcert, STACK_OF(X509) **pcerts,
int exclude_http, const char *pass, const char *desc,
X509_VERIFY_PARAM *vpm)
{
int ret = 0;
char *pass_string;
if (exclude_http && (OPENSSL_strncasecmp(uri, "http://", 7) == 0
|| OPENSSL_strncasecmp(uri, "https://", 8) == 0)) {
BIO_printf(bio_err, "error: HTTP retrieval not allowed for %s\n", desc);
return ret;
}
pass_string = get_passwd(pass, desc);
ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass_string, desc,
NULL, NULL, NULL,
pcert, pcerts, NULL, NULL);
clear_free(pass_string);
if (ret) {
if (pcert != NULL)
warn_cert(uri, *pcert, 0, vpm);
if (pcerts != NULL)
warn_certs(uri, *pcerts, 1, vpm);
} else {
if (pcerts != NULL) {
sk_X509_pop_free(*pcerts, X509_free);
*pcerts = NULL;
}
}
return ret;
}
STACK_OF(X509) *load_certs_multifile(char *files, const char *pass,
const char *desc, X509_VERIFY_PARAM *vpm)
{
STACK_OF(X509) *certs = NULL;
STACK_OF(X509) *result = sk_X509_new_null();
if (files == NULL)
goto err;
if (result == NULL)
goto oom;
while (files != NULL) {
char *next = next_item(files);
if (!load_cert_certs(files, NULL, &certs, 0, pass, desc, vpm))
goto err;
if (!X509_add_certs(result, certs,
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
goto oom;
sk_X509_pop_free(certs, X509_free);
certs = NULL;
files = next;
}
return result;
oom:
BIO_printf(bio_err, "out of memory\n");
err:
sk_X509_pop_free(certs, X509_free);
sk_X509_pop_free(result, X509_free);
return NULL;
}
static X509_STORE *sk_X509_to_store(X509_STORE *store /* may be NULL */,
const STACK_OF(X509) *certs /* may NULL */)
{
int i;
if (store == NULL)
store = X509_STORE_new();
if (store == NULL)
return NULL;
for (i = 0; i < sk_X509_num(certs); i++) {
if (!X509_STORE_add_cert(store, sk_X509_value(certs, i))) {
X509_STORE_free(store);
return NULL;
}
}
return store;
}
/*
* Create cert store structure with certificates read from given file(s).
* Returns pointer to created X509_STORE on success, NULL on error.
*/
X509_STORE *load_certstore(char *input, const char *pass, const char *desc,
X509_VERIFY_PARAM *vpm)
{
X509_STORE *store = NULL;
STACK_OF(X509) *certs = NULL;
while (input != NULL) {
char *next = next_item(input);
int ok;
if (!load_cert_certs(input, NULL, &certs, 1, pass, desc, vpm)) {
X509_STORE_free(store);
return NULL;
}
ok = (store = sk_X509_to_store(store, certs)) != NULL;
sk_X509_pop_free(certs, X509_free);
certs = NULL;
if (!ok)
return NULL;
input = next;
}
return store;
}
/*
* Initialize or extend, if *certs != NULL, a certificate stack.
* The caller is responsible for freeing *certs if its value is left not NULL.
*/
int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs,
const char *pass, const char *desc)
{
int was_NULL = *certs == NULL;
int ret = load_key_certs_crls(uri, FORMAT_UNDEF, maybe_stdin,
pass, desc, NULL, NULL,
NULL, NULL, certs, NULL, NULL);
if (!ret && was_NULL) {
sk_X509_pop_free(*certs, X509_free);
*certs = NULL;
}
return ret;
}
/*
* Initialize or extend, if *crls != NULL, a certificate stack.
* The caller is responsible for freeing *crls if its value is left not NULL.
*/
int load_crls(const char *uri, STACK_OF(X509_CRL) **crls,
const char *pass, const char *desc)
{
int was_NULL = *crls == NULL;
int ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass, desc,
NULL, NULL, NULL,
NULL, NULL, NULL, crls);
if (!ret && was_NULL) {
sk_X509_CRL_pop_free(*crls, X509_CRL_free);
*crls = NULL;
}
return ret;
}
static const char *format2string(int format)
{
switch(format) {
case FORMAT_PEM:
return "PEM";
case FORMAT_ASN1:
return "DER";
}
return NULL;
}
/* Set type expectation, but clear it if objects of different types expected. */
#define SET_EXPECT(expect, val) ((expect) = (expect) < 0 ? (val) : ((expect) == (val) ? (val) : 0))
/*
* Load those types of credentials for which the result pointer is not NULL.
* Reads from stdio if uri is NULL and maybe_stdin is nonzero.
* For non-NULL ppkey, pcert, and pcrl the first suitable value found is loaded.
* If pcerts is non-NULL and *pcerts == NULL then a new cert list is allocated.
* If pcerts is non-NULL then all available certificates are appended to *pcerts
* except any certificate assigned to *pcert.
* If pcrls is non-NULL and *pcrls == NULL then a new list of CRLs is allocated.
* If pcrls is non-NULL then all available CRLs are appended to *pcerts
* except any CRL assigned to *pcrl.
* In any case (also on error) the caller is responsible for freeing all members
* of *pcerts and *pcrls (as far as they are not NULL).
*/
static
int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin,
const char *pass, const char *desc,
EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
EVP_PKEY **pparams,
X509 **pcert, STACK_OF(X509) **pcerts,
X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls,
int suppress_decode_errors)
{
PW_CB_DATA uidata;
OSSL_STORE_CTX *ctx = NULL;
OSSL_LIB_CTX *libctx = app_get0_libctx();
const char *propq = app_get0_propq();
int ncerts = 0;
int ncrls = 0;
const char *failed =
ppkey != NULL ? "key" : ppubkey != NULL ? "public key" :
pparams != NULL ? "params" : pcert != NULL ? "cert" :
pcrl != NULL ? "CRL" : pcerts != NULL ? "certs" :
pcrls != NULL ? "CRLs" : NULL;
int cnt_expectations = 0;
int expect = -1;
const char *input_type;
OSSL_PARAM itp[2];
const OSSL_PARAM *params = NULL;
if (ppkey != NULL) {
*ppkey = NULL;
cnt_expectations++;
SET_EXPECT(expect, OSSL_STORE_INFO_PKEY);
}
if (ppubkey != NULL) {
*ppubkey = NULL;
cnt_expectations++;
SET_EXPECT(expect, OSSL_STORE_INFO_PUBKEY);
}
if (pparams != NULL) {
*pparams = NULL;
cnt_expectations++;
SET_EXPECT(expect, OSSL_STORE_INFO_PARAMS);
}
if (pcert != NULL) {
*pcert = NULL;
cnt_expectations++;
SET_EXPECT(expect, OSSL_STORE_INFO_CERT);
}
if (pcerts != NULL) {
if (*pcerts == NULL && (*pcerts = sk_X509_new_null()) == NULL) {
BIO_printf(bio_err, "Out of memory loading");
goto end;
}
cnt_expectations++;
SET_EXPECT(expect, OSSL_STORE_INFO_CERT);
}
if (pcrl != NULL) {
*pcrl = NULL;
cnt_expectations++;
SET_EXPECT(expect, OSSL_STORE_INFO_CRL);
}
if (pcrls != NULL) {
if (*pcrls == NULL && (*pcrls = sk_X509_CRL_new_null()) == NULL) {
BIO_printf(bio_err, "Out of memory loading");
goto end;
}
cnt_expectations++;
SET_EXPECT(expect, OSSL_STORE_INFO_CRL);
}
if (cnt_expectations == 0) {
BIO_printf(bio_err, "Internal error: nothing to load from %s\n",
uri != NULL ? uri : "<stdin>");
return 0;
}
uidata.password = pass;
uidata.prompt_info = uri;
if ((input_type = format2string(format)) != NULL) {
itp[0] = OSSL_PARAM_construct_utf8_string(OSSL_STORE_PARAM_INPUT_TYPE,
(char *)input_type, 0);
itp[1] = OSSL_PARAM_construct_end();
params = itp;
}
if (uri == NULL) {
BIO *bio;
if (!maybe_stdin) {
BIO_printf(bio_err, "No filename or uri specified for loading");
goto end;
}
uri = "<stdin>";
unbuffer(stdin);
bio = BIO_new_fp(stdin, 0);
if (bio != NULL) {
ctx = OSSL_STORE_attach(bio, "file", libctx, propq,
get_ui_method(), &uidata, params,
NULL, NULL);
BIO_free(bio);
}
} else {
ctx = OSSL_STORE_open_ex(uri, libctx, propq, get_ui_method(), &uidata,
params, NULL, NULL);
}
if (ctx == NULL) {
BIO_printf(bio_err, "Could not open file or uri for loading");
goto end;
}
if (expect > 0 && !OSSL_STORE_expect(ctx, expect))
goto end;
failed = NULL;
while (cnt_expectations > 0 && !OSSL_STORE_eof(ctx)) {
OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
int type, ok = 1;
/*
* This can happen (for example) if we attempt to load a file with
* multiple different types of things in it - but the thing we just
* tried to load wasn't one of the ones we wanted, e.g. if we're trying
* to load a certificate but the file has both the private key and the
* certificate in it. We just retry until eof.
*/
if (info == NULL) {
continue;
}
type = OSSL_STORE_INFO_get_type(info);
switch (type) {
case OSSL_STORE_INFO_PKEY:
if (ppkey != NULL && *ppkey == NULL) {
ok = (*ppkey = OSSL_STORE_INFO_get1_PKEY(info)) != NULL;
cnt_expectations -= ok;
}
/*
* An EVP_PKEY with private parts also holds the public parts,
* so if the caller asked for a public key, and we got a private
* key, we can still pass it back.
*/
if (ok && ppubkey != NULL && *ppubkey == NULL) {
ok = ((*ppubkey = OSSL_STORE_INFO_get1_PKEY(info)) != NULL);
cnt_expectations -= ok;
}
break;
case OSSL_STORE_INFO_PUBKEY:
if (ppubkey != NULL && *ppubkey == NULL) {
ok = ((*ppubkey = OSSL_STORE_INFO_get1_PUBKEY(info)) != NULL);
cnt_expectations -= ok;
}
break;
case OSSL_STORE_INFO_PARAMS:
if (pparams != NULL && *pparams == NULL) {
ok = ((*pparams = OSSL_STORE_INFO_get1_PARAMS(info)) != NULL);
cnt_expectations -= ok;
}
break;
case OSSL_STORE_INFO_CERT:
if (pcert != NULL && *pcert == NULL) {
ok = (*pcert = OSSL_STORE_INFO_get1_CERT(info)) != NULL;
cnt_expectations -= ok;
}
else if (pcerts != NULL)
ok = X509_add_cert(*pcerts,
OSSL_STORE_INFO_get1_CERT(info),
X509_ADD_FLAG_DEFAULT);
ncerts += ok;
break;
case OSSL_STORE_INFO_CRL:
if (pcrl != NULL && *pcrl == NULL) {
ok = (*pcrl = OSSL_STORE_INFO_get1_CRL(info)) != NULL;
cnt_expectations -= ok;
}
else if (pcrls != NULL)
ok = sk_X509_CRL_push(*pcrls, OSSL_STORE_INFO_get1_CRL(info));
ncrls += ok;
break;
default:
/* skip any other type */
break;
}
OSSL_STORE_INFO_free(info);
if (!ok) {
failed = info == NULL ? NULL : OSSL_STORE_INFO_type_string(type);
BIO_printf(bio_err, "Error reading");
break;
}
}
end:
OSSL_STORE_close(ctx);
if (failed == NULL) {
int any = 0;
if ((ppkey != NULL && *ppkey == NULL)
|| (ppubkey != NULL && *ppubkey == NULL)) {
failed = "key";
} else if (pparams != NULL && *pparams == NULL) {
failed = "params";
} else if ((pcert != NULL || pcerts != NULL) && ncerts == 0) {
if (pcert == NULL)
any = 1;
failed = "cert";
} else if ((pcrl != NULL || pcrls != NULL) && ncrls == 0) {
if (pcrl == NULL)
any = 1;
failed = "CRL";
}
if (!suppress_decode_errors) {
if (failed != NULL)
BIO_printf(bio_err, "Could not read");
if (any)
BIO_printf(bio_err, " any");
}
}
if (!suppress_decode_errors && failed != NULL) {
if (desc != NULL && strstr(desc, failed) != NULL) {
BIO_printf(bio_err, " %s", desc);
} else {
BIO_printf(bio_err, " %s", failed);
if (desc != NULL)
BIO_printf(bio_err, " of %s", desc);
}
if (uri != NULL)
BIO_printf(bio_err, " from %s", uri);
BIO_printf(bio_err, "\n");
ERR_print_errors(bio_err);
}
if (suppress_decode_errors || failed == NULL)
/* clear any spurious errors */
ERR_clear_error();
return failed == NULL;
}
int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
const char *pass, const char *desc,
EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
EVP_PKEY **pparams,
X509 **pcert, STACK_OF(X509) **pcerts,
X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls)
{
return load_key_certs_crls_suppress(uri, format, maybe_stdin, pass, desc,
ppkey, ppubkey, pparams, pcert, pcerts,
pcrl, pcrls, 0);
}
#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16)
/* Return error for unknown extensions */
#define X509V3_EXT_DEFAULT 0
/* Print error for unknown extensions */
#define X509V3_EXT_ERROR_UNKNOWN (1L << 16)
/* ASN1 parse unknown extensions */
#define X509V3_EXT_PARSE_UNKNOWN (2L << 16)
/* BIO_dump unknown extensions */
#define X509V3_EXT_DUMP_UNKNOWN (3L << 16)
#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
int set_cert_ex(unsigned long *flags, const char *arg)
{
static const NAME_EX_TBL cert_tbl[] = {
{"compatible", X509_FLAG_COMPAT, 0xffffffffl},
{"ca_default", X509_FLAG_CA, 0xffffffffl},
{"no_header", X509_FLAG_NO_HEADER, 0},
{"no_version", X509_FLAG_NO_VERSION, 0},
{"no_serial", X509_FLAG_NO_SERIAL, 0},
{"no_signame", X509_FLAG_NO_SIGNAME, 0},
{"no_validity", X509_FLAG_NO_VALIDITY, 0},
{"no_subject", X509_FLAG_NO_SUBJECT, 0},
{"no_issuer", X509_FLAG_NO_ISSUER, 0},
{"no_pubkey", X509_FLAG_NO_PUBKEY, 0},
{"no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
{"no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
{"no_aux", X509_FLAG_NO_AUX, 0},
{"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0},
{"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK},
{"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
{"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
{"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
{NULL, 0, 0}
};
return set_multi_opts(flags, arg, cert_tbl);
}
int set_name_ex(unsigned long *flags, const char *arg)
{
static const NAME_EX_TBL ex_tbl[] = {
{"esc_2253", ASN1_STRFLGS_ESC_2253, 0},
{"esc_2254", ASN1_STRFLGS_ESC_2254, 0},
{"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0},
{"esc_msb", ASN1_STRFLGS_ESC_MSB, 0},
{"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0},
{"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0},
{"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0},
{"show_type", ASN1_STRFLGS_SHOW_TYPE, 0},
{"dump_all", ASN1_STRFLGS_DUMP_ALL, 0},
{"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0},
{"dump_der", ASN1_STRFLGS_DUMP_DER, 0},
{"compat", XN_FLAG_COMPAT, 0xffffffffL},
{"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK},
{"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK},
{"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK},
{"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK},
{"dn_rev", XN_FLAG_DN_REV, 0},
{"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
{"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
{"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
{"align", XN_FLAG_FN_ALIGN, 0},
{"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
{"space_eq", XN_FLAG_SPC_EQ, 0},
{"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
{"RFC2253", XN_FLAG_RFC2253, 0xffffffffL},
{"oneline", XN_FLAG_ONELINE, 0xffffffffL},
{"multiline", XN_FLAG_MULTILINE, 0xffffffffL},
{"ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
{NULL, 0, 0}
};
if (set_multi_opts(flags, arg, ex_tbl) == 0)
return 0;
if (*flags != XN_FLAG_COMPAT
&& (*flags & XN_FLAG_SEP_MASK) == 0)
*flags |= XN_FLAG_SEP_CPLUS_SPC;
return 1;
}
int set_dateopt(unsigned long *dateopt, const char *arg)
{
if (OPENSSL_strcasecmp(arg, "rfc_822") == 0)
*dateopt = ASN1_DTFLGS_RFC822;
else if (OPENSSL_strcasecmp(arg, "iso_8601") == 0)
*dateopt = ASN1_DTFLGS_ISO8601;
else
return 0;
return 1;
}
int set_ext_copy(int *copy_type, const char *arg)
{
if (OPENSSL_strcasecmp(arg, "none") == 0)
*copy_type = EXT_COPY_NONE;
else if (OPENSSL_strcasecmp(arg, "copy") == 0)
*copy_type = EXT_COPY_ADD;
else if (OPENSSL_strcasecmp(arg, "copyall") == 0)
*copy_type = EXT_COPY_ALL;
else
return 0;
return 1;
}
int copy_extensions(X509 *x, X509_REQ *req, int copy_type)
{
STACK_OF(X509_EXTENSION) *exts;
int i, ret = 0;
if (x == NULL || req == NULL)
return 0;
if (copy_type == EXT_COPY_NONE)
return 1;
exts = X509_REQ_get_extensions(req);
for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext);
int idx = X509_get_ext_by_OBJ(x, obj, -1);
/* Does extension exist in target? */
if (idx != -1) {
/* If normal copy don't override existing extension */
if (copy_type == EXT_COPY_ADD)
continue;
/* Delete all extensions of same type */
do {
X509_EXTENSION_free(X509_delete_ext(x, idx));
idx = X509_get_ext_by_OBJ(x, obj, -1);
} while (idx != -1);
}
if (!X509_add_ext(x, ext, -1))
goto end;
}
ret = 1;
end:
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
return ret;
}
static int set_multi_opts(unsigned long *flags, const char *arg,
const NAME_EX_TBL * in_tbl)
{
STACK_OF(CONF_VALUE) *vals;
CONF_VALUE *val;
int i, ret = 1;
if (!arg)
return 0;
vals = X509V3_parse_list(arg);
for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
val = sk_CONF_VALUE_value(vals, i);
if (!set_table_opts(flags, val->name, in_tbl))
ret = 0;
}
sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
return ret;
}
static int set_table_opts(unsigned long *flags, const char *arg,
const NAME_EX_TBL * in_tbl)
{
char c;
const NAME_EX_TBL *ptbl;
c = arg[0];
if (c == '-') {
c = 0;
arg++;
} else if (c == '+') {
c = 1;
arg++;
} else {
c = 1;
}
for (ptbl = in_tbl; ptbl->name; ptbl++) {
if (OPENSSL_strcasecmp(arg, ptbl->name) == 0) {
*flags &= ~ptbl->mask;
if (c)
*flags |= ptbl->flag;
else
*flags &= ~ptbl->flag;
return 1;
}
}
return 0;
}
void print_name(BIO *out, const char *title, const X509_NAME *nm)
{
char *buf;
char mline = 0;
int indent = 0;
unsigned long lflags = get_nameopt();
if (out == NULL)
return;
if (title != NULL)
BIO_puts(out, title);
if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
mline = 1;
indent = 4;
}
if (lflags == XN_FLAG_COMPAT) {
buf = X509_NAME_oneline(nm, 0, 0);
BIO_puts(out, buf);
BIO_puts(out, "\n");
OPENSSL_free(buf);
} else {
if (mline)
BIO_puts(out, "\n");
X509_NAME_print_ex(out, nm, indent, lflags);
BIO_puts(out, "\n");
}
}
void print_bignum_var(BIO *out, const BIGNUM *in, const char *var,
int len, unsigned char *buffer)
{
BIO_printf(out, " static unsigned char %s_%d[] = {", var, len);
if (BN_is_zero(in)) {
BIO_printf(out, "\n 0x00");
} else {
int i, l;
l = BN_bn2bin(in, buffer);
for (i = 0; i < l; i++) {
BIO_printf(out, (i % 10) == 0 ? "\n " : " ");
if (i < l - 1)
BIO_printf(out, "0x%02X,", buffer[i]);
else
BIO_printf(out, "0x%02X", buffer[i]);
}
}
BIO_printf(out, "\n };\n");
}
void print_array(BIO *out, const char* title, int len, const unsigned char* d)
{
int i;
BIO_printf(out, "unsigned char %s[%d] = {", title, len);
for (i = 0; i < len; i++) {
if ((i % 10) == 0)
BIO_printf(out, "\n ");
if (i < len - 1)
BIO_printf(out, "0x%02X, ", d[i]);
else
BIO_printf(out, "0x%02X", d[i]);
}
BIO_printf(out, "\n};\n");
}
X509_STORE *setup_verify(const char *CAfile, int noCAfile,
const char *CApath, int noCApath,
const char *CAstore, int noCAstore)
{
X509_STORE *store = X509_STORE_new();
X509_LOOKUP *lookup;
OSSL_LIB_CTX *libctx = app_get0_libctx();
const char *propq = app_get0_propq();
if (store == NULL)
goto end;
if (CAfile != NULL || !noCAfile) {
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
if (lookup == NULL)
goto end;
if (CAfile != NULL) {
if (X509_LOOKUP_load_file_ex(lookup, CAfile, X509_FILETYPE_PEM,
libctx, propq) <= 0) {
BIO_printf(bio_err, "Error loading file %s\n", CAfile);
goto end;
}
} else {
X509_LOOKUP_load_file_ex(lookup, NULL, X509_FILETYPE_DEFAULT,
libctx, propq);
}
}
if (CApath != NULL || !noCApath) {
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
if (lookup == NULL)
goto end;
if (CApath != NULL) {
if (X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM) <= 0) {
BIO_printf(bio_err, "Error loading directory %s\n", CApath);
goto end;
}
} else {
X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
}
}
if (CAstore != NULL || !noCAstore) {
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_store());
if (lookup == NULL)
goto end;
if (!X509_LOOKUP_add_store_ex(lookup, CAstore, libctx, propq)) {
if (CAstore != NULL)
BIO_printf(bio_err, "Error loading store URI %s\n", CAstore);
goto end;
}
}
ERR_clear_error();
return store;
end:
ERR_print_errors(bio_err);
X509_STORE_free(store);
return NULL;
}
static unsigned long index_serial_hash(const OPENSSL_CSTRING *a)
{
const char *n;
n = a[DB_serial];
while (*n == '0')
n++;
return OPENSSL_LH_strhash(n);
}
static int index_serial_cmp(const OPENSSL_CSTRING *a,
const OPENSSL_CSTRING *b)
{
const char *aa, *bb;
for (aa = a[DB_serial]; *aa == '0'; aa++) ;
for (bb = b[DB_serial]; *bb == '0'; bb++) ;
return strcmp(aa, bb);
}
static int index_name_qual(char **a)
{
return (a[0][0] == 'V');
}
static unsigned long index_name_hash(const OPENSSL_CSTRING *a)
{
return OPENSSL_LH_strhash(a[DB_name]);
}
int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
{
return strcmp(a[DB_name], b[DB_name]);
}
static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING)
static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING)
static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING)
static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING)
#undef BSIZE
#define BSIZE 256
BIGNUM *load_serial(const char *serialfile, int *exists, int create,
ASN1_INTEGER **retai)
{
BIO *in = NULL;
BIGNUM *ret = NULL;
char buf[1024];
ASN1_INTEGER *ai = NULL;
ai = ASN1_INTEGER_new();
if (ai == NULL)
goto err;
in = BIO_new_file(serialfile, "r");
if (exists != NULL)
*exists = in != NULL;
if (in == NULL) {
if (!create) {
perror(serialfile);
goto err;
}
ERR_clear_error();
ret = BN_new();
if (ret == NULL) {
BIO_printf(bio_err, "Out of memory\n");
} else if (!rand_serial(ret, ai)) {
BIO_printf(bio_err, "Error creating random number to store in %s\n",
serialfile);
BN_free(ret);
ret = NULL;
}
} else {
if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) {
BIO_printf(bio_err, "Unable to load number from %s\n",
serialfile);
goto err;
}
ret = ASN1_INTEGER_to_BN(ai, NULL);
if (ret == NULL) {
BIO_printf(bio_err, "Error converting number from bin to BIGNUM\n");
goto err;
}
}
if (ret != NULL && retai != NULL) {
*retai = ai;
ai = NULL;
}
err:
if (ret == NULL)
ERR_print_errors(bio_err);
BIO_free(in);
ASN1_INTEGER_free(ai);
return ret;
}
int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial,
ASN1_INTEGER **retai)
{
char buf[1][BSIZE];
BIO *out = NULL;
int ret = 0;
ASN1_INTEGER *ai = NULL;
int j;
if (suffix == NULL)
j = strlen(serialfile);
else
j = strlen(serialfile) + strlen(suffix) + 1;
if (j >= BSIZE) {
BIO_printf(bio_err, "File name too long\n");
goto err;
}
if (suffix == NULL)
OPENSSL_strlcpy(buf[0], serialfile, BSIZE);
else {
#ifndef OPENSSL_SYS_VMS
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix);
#else
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix);
#endif
}
out = BIO_new_file(buf[0], "w");
if (out == NULL) {
goto err;
}
if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) {
BIO_printf(bio_err, "error converting serial to ASN.1 format\n");
goto err;
}
i2a_ASN1_INTEGER(out, ai);
BIO_puts(out, "\n");
ret = 1;
if (retai) {
*retai = ai;
ai = NULL;
}
err:
if (!ret)
ERR_print_errors(bio_err);
BIO_free_all(out);
ASN1_INTEGER_free(ai);
return ret;
}
int rotate_serial(const char *serialfile, const char *new_suffix,
const char *old_suffix)
{
char buf[2][BSIZE];
int i, j;
i = strlen(serialfile) + strlen(old_suffix);
j = strlen(serialfile) + strlen(new_suffix);
if (i > j)
j = i;
if (j + 1 >= BSIZE) {
BIO_printf(bio_err, "File name too long\n");
goto err;
}
#ifndef OPENSSL_SYS_VMS
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, new_suffix);
j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", serialfile, old_suffix);
#else
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix);
j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", serialfile, old_suffix);
#endif
if (rename(serialfile, buf[1]) < 0 && errno != ENOENT
#ifdef ENOTDIR
&& errno != ENOTDIR
#endif
) {
BIO_printf(bio_err,
"Unable to rename %s to %s\n", serialfile, buf[1]);
perror("reason");
goto err;
}
if (rename(buf[0], serialfile) < 0) {
BIO_printf(bio_err,
"Unable to rename %s to %s\n", buf[0], serialfile);
perror("reason");
rename(buf[1], serialfile);
goto err;
}
return 1;
err:
ERR_print_errors(bio_err);
return 0;
}
int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
{
BIGNUM *btmp;
int ret = 0;
btmp = b == NULL ? BN_new() : b;
if (btmp == NULL)
return 0;
if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
goto error;
if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
goto error;
ret = 1;
error:
if (btmp != b)
BN_free(btmp);
return ret;
}
CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr)
{
CA_DB *retdb = NULL;
TXT_DB *tmpdb = NULL;
BIO *in;
CONF *dbattr_conf = NULL;
char buf[BSIZE];
#ifndef OPENSSL_NO_POSIX_IO
FILE *dbfp;
struct stat dbst;
#endif
in = BIO_new_file(dbfile, "r");
if (in == NULL)
goto err;
#ifndef OPENSSL_NO_POSIX_IO
BIO_get_fp(in, &dbfp);
if (fstat(fileno(dbfp), &dbst) == -1) {
ERR_raise_data(ERR_LIB_SYS, errno,
"calling fstat(%s)", dbfile);
goto err;
}
#endif
if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL)
goto err;
#ifndef OPENSSL_SYS_VMS
BIO_snprintf(buf, sizeof(buf), "%s.attr", dbfile);
#else
BIO_snprintf(buf, sizeof(buf), "%s-attr", dbfile);
#endif
dbattr_conf = app_load_config_quiet(buf);
retdb = app_malloc(sizeof(*retdb), "new DB");
retdb->db = tmpdb;
tmpdb = NULL;
if (db_attr)
retdb->attributes = *db_attr;
else {
retdb->attributes.unique_subject = 1;
}
if (dbattr_conf) {
char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject");
if (p) {
retdb->attributes.unique_subject = parse_yesno(p, 1);
}
}
retdb->dbfname = OPENSSL_strdup(dbfile);
#ifndef OPENSSL_NO_POSIX_IO
retdb->dbst = dbst;
#endif
err:
ERR_print_errors(bio_err);
NCONF_free(dbattr_conf);
TXT_DB_free(tmpdb);
BIO_free_all(in);
return retdb;
}
/*
* Returns > 0 on success, <= 0 on error
*/
int index_index(CA_DB *db)
{
if (!TXT_DB_create_index(db->db, DB_serial, NULL,
LHASH_HASH_FN(index_serial),
LHASH_COMP_FN(index_serial))) {
BIO_printf(bio_err,
"Error creating serial number index:(%ld,%ld,%ld)\n",
db->db->error, db->db->arg1, db->db->arg2);
goto err;
}
if (db->attributes.unique_subject
&& !TXT_DB_create_index(db->db, DB_name, index_name_qual,
LHASH_HASH_FN(index_name),
LHASH_COMP_FN(index_name))) {
BIO_printf(bio_err, "Error creating name index:(%ld,%ld,%ld)\n",
db->db->error, db->db->arg1, db->db->arg2);
goto err;
}
return 1;
err:
ERR_print_errors(bio_err);
return 0;
}
int save_index(const char *dbfile, const char *suffix, CA_DB *db)
{
char buf[3][BSIZE];
BIO *out;
int j;
j = strlen(dbfile) + strlen(suffix);
if (j + 6 >= BSIZE) {
BIO_printf(bio_err, "File name too long\n");
goto err;
}
#ifndef OPENSSL_SYS_VMS
j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr", dbfile);
j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.attr.%s", dbfile, suffix);
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, suffix);
#else
j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile);
j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix);
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, suffix);
#endif
out = BIO_new_file(buf[0], "w");
if (out == NULL) {
perror(dbfile);
BIO_printf(bio_err, "Unable to open '%s'\n", dbfile);
goto err;
}
j = TXT_DB_write(out, db->db);
BIO_free(out);
if (j <= 0)
goto err;
out = BIO_new_file(buf[1], "w");
if (out == NULL) {
perror(buf[2]);
BIO_printf(bio_err, "Unable to open '%s'\n", buf[2]);
goto err;
}
BIO_printf(out, "unique_subject = %s\n",
db->attributes.unique_subject ? "yes" : "no");
BIO_free(out);
return 1;
err:
ERR_print_errors(bio_err);
return 0;
}
int rotate_index(const char *dbfile, const char *new_suffix,
const char *old_suffix)
{
char buf[5][BSIZE];
int i, j;
i = strlen(dbfile) + strlen(old_suffix);
j = strlen(dbfile) + strlen(new_suffix);
if (i > j)
j = i;
if (j + 6 >= BSIZE) {
BIO_printf(bio_err, "File name too long\n");
goto err;
}
#ifndef OPENSSL_SYS_VMS
j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s.attr", dbfile);
j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix);
j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr.%s", dbfile, new_suffix);
j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", dbfile, old_suffix);
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, new_suffix);
#else
j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile);
j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s-attr-%s", dbfile, old_suffix);
j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix);
j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix);
j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix);
#endif
if (rename(dbfile, buf[1]) < 0 && errno != ENOENT
#ifdef ENOTDIR
&& errno != ENOTDIR
#endif
) {
BIO_printf(bio_err, "Unable to rename %s to %s\n", dbfile, buf[1]);
perror("reason");
goto err;
}
if (rename(buf[0], dbfile) < 0) {
BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[0], dbfile);
perror("reason");
rename(buf[1], dbfile);
goto err;
}
if (rename(buf[4], buf[3]) < 0 && errno != ENOENT
#ifdef ENOTDIR
&& errno != ENOTDIR
#endif
) {
BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[4], buf[3]);
perror("reason");
rename(dbfile, buf[0]);
rename(buf[1], dbfile);
goto err;
}
if (rename(buf[2], buf[4]) < 0) {
BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[2], buf[4]);
perror("reason");
rename(buf[3], buf[4]);
rename(dbfile, buf[0]);
rename(buf[1], dbfile);
goto err;
}
return 1;
err:
ERR_print_errors(bio_err);
return 0;
}
void free_index(CA_DB *db)
{
if (db) {
TXT_DB_free(db->db);
OPENSSL_free(db->dbfname);
OPENSSL_free(db);
}
}
int parse_yesno(const char *str, int def)
{
if (str) {
switch (*str) {
case 'f': /* false */
case 'F': /* FALSE */
case 'n': /* no */
case 'N': /* NO */
case '0': /* 0 */
return 0;
case 't': /* true */
case 'T': /* TRUE */
case 'y': /* yes */
case 'Y': /* YES */
case '1': /* 1 */
return 1;
}
}
return def;
}
/*
* name is expected to be in the format /type0=value0/type1=value1/type2=...
* where + can be used instead of / to form multi-valued RDNs if canmulti
* and characters may be escaped by \
*/
X509_NAME *parse_name(const char *cp, int chtype, int canmulti,
const char *desc)
{
int nextismulti = 0;
char *work;
X509_NAME *n;
if (*cp++ != '/') {
BIO_printf(bio_err,
"%s: %s name is expected to be in the format "
"/type0=value0/type1=value1/type2=... where characters may "
"be escaped by \\. This name is not in that format: '%s'\n",
opt_getprog(), desc, --cp);
return NULL;
}
n = X509_NAME_new();
if (n == NULL) {
BIO_printf(bio_err, "%s: Out of memory\n", opt_getprog());
return NULL;
}
work = OPENSSL_strdup(cp);
if (work == NULL) {
BIO_printf(bio_err, "%s: Error copying %s name input\n",
opt_getprog(), desc);
goto err;
}
while (*cp != '\0') {
char *bp = work;
char *typestr = bp;
unsigned char *valstr;
int nid;
int ismulti = nextismulti;
nextismulti = 0;
/* Collect the type */
while (*cp != '\0' && *cp != '=')
*bp++ = *cp++;
*bp++ = '\0';
if (*cp == '\0') {
BIO_printf(bio_err,
"%s: Missing '=' after RDN type string '%s' in %s name string\n",
opt_getprog(), typestr, desc);
goto err;
}
++cp;
/* Collect the value. */
valstr = (unsigned char *)bp;
for (; *cp != '\0' && *cp != '/'; *bp++ = *cp++) {
/* unescaped '+' symbol string signals further member of multiRDN */
if (canmulti && *cp == '+') {
nextismulti = 1;
break;
}
if (*cp == '\\' && *++cp == '\0') {
BIO_printf(bio_err,
"%s: Escape character at end of %s name string\n",
opt_getprog(), desc);
goto err;
}
}
*bp++ = '\0';
/* If not at EOS (must be + or /), move forward. */
if (*cp != '\0')
++cp;
/* Parse */
nid = OBJ_txt2nid(typestr);
if (nid == NID_undef) {
BIO_printf(bio_err,
"%s: Skipping unknown %s name attribute \"%s\"\n",
opt_getprog(), desc, typestr);
if (ismulti)
BIO_printf(bio_err,
"Hint: a '+' in a value string needs be escaped using '\\' else a new member of a multi-valued RDN is expected\n");
continue;
}
if (*valstr == '\0') {
BIO_printf(bio_err,
"%s: No value provided for %s name attribute \"%s\", skipped\n",
opt_getprog(), desc, typestr);
continue;
}
if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
valstr, strlen((char *)valstr),
-1, ismulti ? -1 : 0)) {
ERR_print_errors(bio_err);
BIO_printf(bio_err,
"%s: Error adding %s name attribute \"/%s=%s\"\n",
opt_getprog(), desc, typestr ,valstr);
goto err;
}
}
OPENSSL_free(work);
return n;
err:
X509_NAME_free(n);
OPENSSL_free(work);
return NULL;
}
/*
* Read whole contents of a BIO into an allocated memory buffer and return
* it.
*/
int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
{
BIO *mem;
int len, ret;
unsigned char tbuf[1024];
mem = BIO_new(BIO_s_mem());
if (mem == NULL)
return -1;
for (;;) {
if ((maxlen != -1) && maxlen < 1024)
len = maxlen;
else
len = 1024;
len = BIO_read(in, tbuf, len);
if (len < 0) {
BIO_free(mem);
return -1;
}
if (len == 0)
break;
if (BIO_write(mem, tbuf, len) != len) {
BIO_free(mem);
return -1;
}
maxlen -= len;
if (maxlen == 0)
break;
}
ret = BIO_get_mem_data(mem, (char **)out);
BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
BIO_free(mem);
return ret;
}
int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value)
{
int rv = 0;
char *stmp, *vtmp = NULL;
stmp = OPENSSL_strdup(value);
if (stmp == NULL)
return -1;
vtmp = strchr(stmp, ':');
if (vtmp == NULL)
goto err;
*vtmp = 0;
vtmp++;
rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp);
err:
OPENSSL_free(stmp);
return rv;
}
static void nodes_print(const char *name, STACK_OF(X509_POLICY_NODE) *nodes)
{
X509_POLICY_NODE *node;
int i;
BIO_printf(bio_err, "%s Policies:", name);
if (nodes) {
BIO_puts(bio_err, "\n");
for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) {
node = sk_X509_POLICY_NODE_value(nodes, i);
X509_POLICY_NODE_print(bio_err, node, 2);
}
} else {
BIO_puts(bio_err, " <empty>\n");
}
}
void policies_print(X509_STORE_CTX *ctx)
{
X509_POLICY_TREE *tree;
int explicit_policy;
tree = X509_STORE_CTX_get0_policy_tree(ctx);
explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx);
BIO_printf(bio_err, "Require explicit Policy: %s\n",
explicit_policy ? "True" : "False");
nodes_print("Authority", X509_policy_tree_get0_policies(tree));
nodes_print("User", X509_policy_tree_get0_user_policies(tree));
}
/*-
* next_protos_parse parses a comma separated list of strings into a string
* in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
* outlen: (output) set to the length of the resulting buffer on success.
* err: (maybe NULL) on failure, an error message line is written to this BIO.
* in: a NUL terminated string like "abc,def,ghi"
*
* returns: a malloc'd buffer or NULL on failure.
*/
unsigned char *next_protos_parse(size_t *outlen, const char *in)
{
size_t len;
unsigned char *out;
size_t i, start = 0;
size_t skipped = 0;
len = strlen(in);
if (len == 0 || len >= 65535)
return NULL;
out = app_malloc(len + 1, "NPN buffer");
for (i = 0; i <= len; ++i) {
if (i == len || in[i] == ',') {
/*
* Zero-length ALPN elements are invalid on the wire, we could be
* strict and reject the entire string, but just ignoring extra
* commas seems harmless and more friendly.
*
* Every comma we skip in this way puts the input buffer another
* byte ahead of the output buffer, so all stores into the output
* buffer need to be decremented by the number commas skipped.
*/
if (i == start) {
++start;
++skipped;
continue;
}
if (i - start > 255) {
OPENSSL_free(out);
return NULL;
}
out[start-skipped] = (unsigned char)(i - start);
start = i + 1;
} else {
out[i + 1 - skipped] = in[i];
}
}
if (len <= skipped) {
OPENSSL_free(out);
return NULL;
}
*outlen = len + 1 - skipped;
return out;
}
void print_cert_checks(BIO *bio, X509 *x,
const char *checkhost,
const char *checkemail, const char *checkip)
{
if (x == NULL)
return;
if (checkhost) {
BIO_printf(bio, "Hostname %s does%s match certificate\n",
checkhost,
X509_check_host(x, checkhost, 0, 0, NULL) == 1
? "" : " NOT");
}
if (checkemail) {
BIO_printf(bio, "Email %s does%s match certificate\n",
checkemail, X509_check_email(x, checkemail, 0, 0)
? "" : " NOT");
}
if (checkip) {
BIO_printf(bio, "IP %s does%s match certificate\n",
checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT");
}
}
static int do_pkey_ctx_init(EVP_PKEY_CTX *pkctx, STACK_OF(OPENSSL_STRING) *opts)
{
int i;
if (opts == NULL)
return 1;
for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
char *opt = sk_OPENSSL_STRING_value(opts, i);
if (pkey_ctrl_string(pkctx, opt) <= 0) {
BIO_printf(bio_err, "parameter error \"%s\"\n", opt);
ERR_print_errors(bio_err);
return 0;
}
}
return 1;
}
static int do_x509_init(X509 *x, STACK_OF(OPENSSL_STRING) *opts)
{
int i;
if (opts == NULL)
return 1;
for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
char *opt = sk_OPENSSL_STRING_value(opts, i);
if (x509_ctrl_string(x, opt) <= 0) {
BIO_printf(bio_err, "parameter error \"%s\"\n", opt);
ERR_print_errors(bio_err);
return 0;
}
}
return 1;
}
static int do_x509_req_init(X509_REQ *x, STACK_OF(OPENSSL_STRING) *opts)
{
int i;
if (opts == NULL)
return 1;
for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
char *opt = sk_OPENSSL_STRING_value(opts, i);
if (x509_req_ctrl_string(x, opt) <= 0) {
BIO_printf(bio_err, "parameter error \"%s\"\n", opt);
ERR_print_errors(bio_err);
return 0;
}
}
return 1;
}
static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey,
const char *md, STACK_OF(OPENSSL_STRING) *sigopts)
{
EVP_PKEY_CTX *pkctx = NULL;
char def_md[80];
if (ctx == NULL)
return 0;
/*
* EVP_PKEY_get_default_digest_name() returns 2 if the digest is mandatory
* for this algorithm.
*/
if (EVP_PKEY_get_default_digest_name(pkey, def_md, sizeof(def_md)) == 2
&& strcmp(def_md, "UNDEF") == 0) {
/* The signing algorithm requires there to be no digest */
md = NULL;
}
return EVP_DigestSignInit_ex(ctx, &pkctx, md, app_get0_libctx(),
app_get0_propq(), pkey, NULL)
&& do_pkey_ctx_init(pkctx, sigopts);
}
static int adapt_keyid_ext(X509 *cert, X509V3_CTX *ext_ctx,
const char *name, const char *value, int add_default)
{
const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert);
X509_EXTENSION *new_ext = X509V3_EXT_nconf(NULL, ext_ctx, name, value);
int idx, rv = 0;
if (new_ext == NULL)
return rv;
idx = X509v3_get_ext_by_OBJ(exts, X509_EXTENSION_get_object(new_ext), -1);
if (idx >= 0) {
X509_EXTENSION *found_ext = X509v3_get_ext(exts, idx);
ASN1_OCTET_STRING *data = X509_EXTENSION_get_data(found_ext);
int disabled = ASN1_STRING_length(data) <= 2; /* config said "none" */
if (disabled) {
X509_delete_ext(cert, idx);
X509_EXTENSION_free(found_ext);
} /* else keep existing key identifier, which might be outdated */
rv = 1;
} else {
rv = !add_default || X509_add_ext(cert, new_ext, -1);
}
X509_EXTENSION_free(new_ext);
return rv;
}
/* Ensure RFC 5280 compliance, adapt keyIDs as needed, and sign the cert info */
int do_X509_sign(X509 *cert, EVP_PKEY *pkey, const char *md,
STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx)
{
const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert);
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
int self_sign;
int rv = 0;
if (sk_X509_EXTENSION_num(exts /* may be NULL */) > 0) {
/* Prevent X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3 */
if (!X509_set_version(cert, X509_VERSION_3))
goto end;
/*
* Add default SKID before such that default AKID can make use of it
* in case the certificate is self-signed
*/
/* Prevent X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER */
if (!adapt_keyid_ext(cert, ext_ctx, "subjectKeyIdentifier", "hash", 1))
goto end;
/* Prevent X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER */
ERR_set_mark();
self_sign = X509_check_private_key(cert, pkey);
ERR_pop_to_mark();
if (!adapt_keyid_ext(cert, ext_ctx, "authorityKeyIdentifier",
"keyid, issuer", !self_sign))
goto end;
}
if (mctx != NULL && do_sign_init(mctx, pkey, md, sigopts) > 0)
rv = (X509_sign_ctx(cert, mctx) > 0);
end:
EVP_MD_CTX_free(mctx);
return rv;
}
/* Sign the certificate request info */
int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const char *md,
STACK_OF(OPENSSL_STRING) *sigopts)
{
int rv = 0;
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
if (do_sign_init(mctx, pkey, md, sigopts) > 0)
rv = (X509_REQ_sign_ctx(x, mctx) > 0);
EVP_MD_CTX_free(mctx);
return rv;
}
/* Sign the CRL info */
int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const char *md,
STACK_OF(OPENSSL_STRING) *sigopts)
{
int rv = 0;
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
if (do_sign_init(mctx, pkey, md, sigopts) > 0)
rv = (X509_CRL_sign_ctx(x, mctx) > 0);
EVP_MD_CTX_free(mctx);
return rv;
}
/*
* do_X509_verify returns 1 if the signature is valid,
* 0 if the signature check fails, or -1 if error occurs.
*/
int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts)
{
int rv = 0;
if (do_x509_init(x, vfyopts) > 0)
rv = X509_verify(x, pkey);
else
rv = -1;
return rv;
}
/*
* do_X509_REQ_verify returns 1 if the signature is valid,
* 0 if the signature check fails, or -1 if error occurs.
*/
int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey,
STACK_OF(OPENSSL_STRING) *vfyopts)
{
int rv = 0;
if (do_x509_req_init(x, vfyopts) > 0)
rv = X509_REQ_verify_ex(x, pkey,
app_get0_libctx(), app_get0_propq());
else
rv = -1;
return rv;
}
/* Get first http URL from a DIST_POINT structure */
static const char *get_dp_url(DIST_POINT *dp)
{
GENERAL_NAMES *gens;
GENERAL_NAME *gen;
int i, gtype;
ASN1_STRING *uri;
if (!dp->distpoint || dp->distpoint->type != 0)
return NULL;
gens = dp->distpoint->name.fullname;
for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
gen = sk_GENERAL_NAME_value(gens, i);
uri = GENERAL_NAME_get0_value(gen, &gtype);
if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) {
const char *uptr = (const char *)ASN1_STRING_get0_data(uri);
if (IS_HTTP(uptr)) /* can/should not use HTTPS here */
return uptr;
}
}
return NULL;
}
/*
* Look through a CRLDP structure and attempt to find an http URL to
* downloads a CRL from.
*/
static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp)
{
int i;
const char *urlptr = NULL;
for (i = 0; i < sk_DIST_POINT_num(crldp); i++) {
DIST_POINT *dp = sk_DIST_POINT_value(crldp, i);
urlptr = get_dp_url(dp);
if (urlptr != NULL)
return load_crl(urlptr, FORMAT_UNDEF, 0, "CRL via CDP");
}
return NULL;
}
/*
* Example of downloading CRLs from CRLDP:
* not usable for real world as it always downloads and doesn't cache anything.
*/
static STACK_OF(X509_CRL) *crls_http_cb(const X509_STORE_CTX *ctx,
const X509_NAME *nm)
{
X509 *x;
STACK_OF(X509_CRL) *crls = NULL;
X509_CRL *crl;
STACK_OF(DIST_POINT) *crldp;
crls = sk_X509_CRL_new_null();
if (!crls)
return NULL;
x = X509_STORE_CTX_get_current_cert(ctx);
crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
crl = load_crl_crldp(crldp);
sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
if (!crl) {
sk_X509_CRL_free(crls);
return NULL;
}
sk_X509_CRL_push(crls, crl);
/* Try to download delta CRL */
crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL);
crl = load_crl_crldp(crldp);
sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
if (crl)
sk_X509_CRL_push(crls, crl);
return crls;
}
void store_setup_crl_download(X509_STORE *st)
{
X509_STORE_set_lookup_crls_cb(st, crls_http_cb);
}
#ifndef OPENSSL_NO_SOCK
static const char *tls_error_hint(void)
{
unsigned long err = ERR_peek_error();
if (ERR_GET_LIB(err) != ERR_LIB_SSL)
err = ERR_peek_last_error();
if (ERR_GET_LIB(err) != ERR_LIB_SSL)
return NULL;
switch (ERR_GET_REASON(err)) {
case SSL_R_WRONG_VERSION_NUMBER:
return "The server does not support (a suitable version of) TLS";
case SSL_R_UNKNOWN_PROTOCOL:
return "The server does not support HTTPS";
case SSL_R_CERTIFICATE_VERIFY_FAILED:
return "Cannot authenticate server via its TLS certificate, likely due to mismatch with our trusted TLS certs or missing revocation status";
case SSL_AD_REASON_OFFSET + TLS1_AD_UNKNOWN_CA:
return "Server did not accept our TLS certificate, likely due to mismatch with server's trust anchor or missing revocation status";
case SSL_AD_REASON_OFFSET + SSL3_AD_HANDSHAKE_FAILURE:
return "TLS handshake failure. Possibly the server requires our TLS certificate but did not receive it";
default: /* no error or no hint available for error */
return NULL;
}
}
/* HTTP callback function that supports TLS connection also via HTTPS proxy */
BIO *app_http_tls_cb(BIO *bio, void *arg, int connect, int detail)
{
APP_HTTP_TLS_INFO *info = (APP_HTTP_TLS_INFO *)arg;
SSL_CTX *ssl_ctx = info->ssl_ctx;
if (ssl_ctx == NULL) /* not using TLS */
return bio;
if (connect) {
SSL *ssl;
BIO *sbio = NULL;
+ X509_STORE *ts = SSL_CTX_get_cert_store(ssl_ctx);
+ X509_VERIFY_PARAM *vpm = X509_STORE_get0_param(ts);
+ const char *host = vpm == NULL ? NULL :
+ X509_VERIFY_PARAM_get0_host(vpm, 0 /* first hostname */);
/* adapt after fixing callback design flaw, see #17088 */
if ((info->use_proxy
&& !OSSL_HTTP_proxy_connect(bio, info->server, info->port,
NULL, NULL, /* no proxy credentials */
info->timeout, bio_err, opt_getprog()))
|| (sbio = BIO_new(BIO_f_ssl())) == NULL) {
return NULL;
}
if (ssl_ctx == NULL || (ssl = SSL_new(ssl_ctx)) == NULL) {
BIO_free(sbio);
return NULL;
}
- /* adapt after fixing callback design flaw, see #17088 */
- SSL_set_tlsext_host_name(ssl, info->server); /* not critical to do */
+ if (vpm != NULL)
+ SSL_set_tlsext_host_name(ssl, host /* may be NULL */);
SSL_set_connect_state(ssl);
BIO_set_ssl(sbio, ssl, BIO_CLOSE);
bio = BIO_push(sbio, bio);
}
if (!connect) {
const char *hint;
BIO *cbio;
if (!detail) { /* disconnecting after error */
hint = tls_error_hint();
if (hint != NULL)
ERR_add_error_data(2, " : ", hint);
}
if (ssl_ctx != NULL) {
(void)ERR_set_mark();
BIO_ssl_shutdown(bio);
cbio = BIO_pop(bio); /* connect+HTTP BIO */
BIO_free(bio); /* SSL BIO */
(void)ERR_pop_to_mark(); /* hide SSL_R_READ_BIO_NOT_SET etc. */
bio = cbio;
}
}
return bio;
}
void APP_HTTP_TLS_INFO_free(APP_HTTP_TLS_INFO *info)
{
if (info != NULL) {
SSL_CTX_free(info->ssl_ctx);
OPENSSL_free(info);
}
}
ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy,
const char *no_proxy, SSL_CTX *ssl_ctx,
const STACK_OF(CONF_VALUE) *headers,
long timeout, const char *expected_content_type,
const ASN1_ITEM *it)
{
APP_HTTP_TLS_INFO info;
char *server;
char *port;
int use_ssl;
BIO *mem;
ASN1_VALUE *resp = NULL;
if (url == NULL || it == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (!OSSL_HTTP_parse_url(url, &use_ssl, NULL /* userinfo */, &server, &port,
NULL /* port_num, */, NULL, NULL, NULL))
return NULL;
if (use_ssl && ssl_ctx == NULL) {
ERR_raise_data(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER,
"missing SSL_CTX");
goto end;
}
if (!use_ssl && ssl_ctx != NULL) {
ERR_raise_data(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT,
"SSL_CTX given but use_ssl == 0");
goto end;
}
info.server = server;
info.port = port;
info.use_proxy = /* workaround for callback design flaw, see #17088 */
OSSL_HTTP_adapt_proxy(proxy, no_proxy, server, use_ssl) != NULL;
info.timeout = timeout;
info.ssl_ctx = ssl_ctx;
mem = OSSL_HTTP_get(url, proxy, no_proxy, NULL /* bio */, NULL /* rbio */,
app_http_tls_cb, &info, 0 /* buf_size */, headers,
expected_content_type, 1 /* expect_asn1 */,
OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout);
resp = ASN1_item_d2i_bio(it, mem, NULL);
BIO_free(mem);
end:
OPENSSL_free(server);
OPENSSL_free(port);
return resp;
}
ASN1_VALUE *app_http_post_asn1(const char *host, const char *port,
const char *path, const char *proxy,
const char *no_proxy, SSL_CTX *ssl_ctx,
const STACK_OF(CONF_VALUE) *headers,
const char *content_type,
ASN1_VALUE *req, const ASN1_ITEM *req_it,
const char *expected_content_type,
long timeout, const ASN1_ITEM *rsp_it)
{
int use_ssl = ssl_ctx != NULL;
APP_HTTP_TLS_INFO info;
BIO *rsp, *req_mem = ASN1_item_i2d_mem_bio(req_it, req);
ASN1_VALUE *res;
if (req_mem == NULL)
return NULL;
info.server = host;
info.port = port;
info.use_proxy = /* workaround for callback design flaw, see #17088 */
OSSL_HTTP_adapt_proxy(proxy, no_proxy, host, use_ssl) != NULL;
info.timeout = timeout;
info.ssl_ctx = ssl_ctx;
rsp = OSSL_HTTP_transfer(NULL, host, port, path, use_ssl,
proxy, no_proxy, NULL /* bio */, NULL /* rbio */,
app_http_tls_cb, &info,
0 /* buf_size */, headers, content_type, req_mem,
expected_content_type, 1 /* expect_asn1 */,
OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout,
0 /* keep_alive */);
BIO_free(req_mem);
res = ASN1_item_d2i_bio(rsp_it, rsp, NULL);
BIO_free(rsp);
return res;
}
#endif
/*
* Platform-specific sections
*/
#if defined(_WIN32)
# ifdef fileno
# undef fileno
# define fileno(a) (int)_fileno(a)
# endif
# include <windows.h>
# include <tchar.h>
static int WIN32_rename(const char *from, const char *to)
{
TCHAR *tfrom = NULL, *tto;
DWORD err;
int ret = 0;
if (sizeof(TCHAR) == 1) {
tfrom = (TCHAR *)from;
tto = (TCHAR *)to;
} else { /* UNICODE path */
size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1;
tfrom = malloc(sizeof(*tfrom) * (flen + tlen));
if (tfrom == NULL)
goto err;
tto = tfrom + flen;
# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
if (!MultiByteToWideChar(CP_ACP, 0, from, flen, (WCHAR *)tfrom, flen))
# endif
for (i = 0; i < flen; i++)
tfrom[i] = (TCHAR)from[i];
# if !defined(_WIN32_WCE) || _WIN32_WCE>=101
if (!MultiByteToWideChar(CP_ACP, 0, to, tlen, (WCHAR *)tto, tlen))
# endif
for (i = 0; i < tlen; i++)
tto[i] = (TCHAR)to[i];
}
if (MoveFile(tfrom, tto))
goto ok;
err = GetLastError();
if (err == ERROR_ALREADY_EXISTS || err == ERROR_FILE_EXISTS) {
if (DeleteFile(tto) && MoveFile(tfrom, tto))
goto ok;
err = GetLastError();
}
if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
errno = ENOENT;
else if (err == ERROR_ACCESS_DENIED)
errno = EACCES;
else
errno = EINVAL; /* we could map more codes... */
err:
ret = -1;
ok:
if (tfrom != NULL && tfrom != (TCHAR *)from)
free(tfrom);
return ret;
}
#endif
/* app_tminterval section */
#if defined(_WIN32)
double app_tminterval(int stop, int usertime)
{
FILETIME now;
double ret = 0;
static ULARGE_INTEGER tmstart;
static int warning = 1;
# ifdef _WIN32_WINNT
static HANDLE proc = NULL;
if (proc == NULL) {
if (check_winnt())
proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,
GetCurrentProcessId());
if (proc == NULL)
proc = (HANDLE) - 1;
}
if (usertime && proc != (HANDLE) - 1) {
FILETIME junk;
GetProcessTimes(proc, &junk, &junk, &junk, &now);
} else
# endif
{
SYSTEMTIME systime;
if (usertime && warning) {
BIO_printf(bio_err, "To get meaningful results, run "
"this program on idle system.\n");
warning = 0;
}
GetSystemTime(&systime);
SystemTimeToFileTime(&systime, &now);
}
if (stop == TM_START) {
tmstart.u.LowPart = now.dwLowDateTime;
tmstart.u.HighPart = now.dwHighDateTime;
} else {
ULARGE_INTEGER tmstop;
tmstop.u.LowPart = now.dwLowDateTime;
tmstop.u.HighPart = now.dwHighDateTime;
ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart) * 1e-7;
}
return ret;
}
#elif defined(OPENSSL_SYS_VXWORKS)
# include <time.h>
double app_tminterval(int stop, int usertime)
{
double ret = 0;
# ifdef CLOCK_REALTIME
static struct timespec tmstart;
struct timespec now;
# else
static unsigned long tmstart;
unsigned long now;
# endif
static int warning = 1;
if (usertime && warning) {
BIO_printf(bio_err, "To get meaningful results, run "
"this program on idle system.\n");
warning = 0;
}
# ifdef CLOCK_REALTIME
clock_gettime(CLOCK_REALTIME, &now);
if (stop == TM_START)
tmstart = now;
else
ret = ((now.tv_sec + now.tv_nsec * 1e-9)
- (tmstart.tv_sec + tmstart.tv_nsec * 1e-9));
# else
now = tickGet();
if (stop == TM_START)
tmstart = now;
else
ret = (now - tmstart) / (double)sysClkRateGet();
# endif
return ret;
}
#elif defined(_SC_CLK_TCK) /* by means of unistd.h */
# include <sys/times.h>
double app_tminterval(int stop, int usertime)
{
double ret = 0;
struct tms rus;
clock_t now = times(&rus);
static clock_t tmstart;
if (usertime)
now = rus.tms_utime;
if (stop == TM_START) {
tmstart = now;
} else {
long int tck = sysconf(_SC_CLK_TCK);
ret = (now - tmstart) / (double)tck;
}
return ret;
}
#else
# include <sys/time.h>
# include <sys/resource.h>
double app_tminterval(int stop, int usertime)
{
double ret = 0;
struct rusage rus;
struct timeval now;
static struct timeval tmstart;
if (usertime)
getrusage(RUSAGE_SELF, &rus), now = rus.ru_utime;
else
gettimeofday(&now, NULL);
if (stop == TM_START)
tmstart = now;
else
ret = ((now.tv_sec + now.tv_usec * 1e-6)
- (tmstart.tv_sec + tmstart.tv_usec * 1e-6));
return ret;
}
#endif
int app_access(const char* name, int flag)
{
#ifdef _WIN32
return _access(name, flag);
#else
return access(name, flag);
#endif
}
int app_isdir(const char *name)
{
return opt_isdir(name);
}
/* raw_read|write section */
#if defined(__VMS)
# include "vms_term_sock.h"
static int stdin_sock = -1;
static void close_stdin_sock(void)
{
TerminalSocket (TERM_SOCK_DELETE, &stdin_sock);
}
int fileno_stdin(void)
{
if (stdin_sock == -1) {
TerminalSocket(TERM_SOCK_CREATE, &stdin_sock);
atexit(close_stdin_sock);
}
return stdin_sock;
}
#else
int fileno_stdin(void)
{
return fileno(stdin);
}
#endif
int fileno_stdout(void)
{
return fileno(stdout);
}
#if defined(_WIN32) && defined(STD_INPUT_HANDLE)
int raw_read_stdin(void *buf, int siz)
{
DWORD n;
if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL))
return n;
else
return -1;
}
#elif defined(__VMS)
# include <sys/socket.h>
int raw_read_stdin(void *buf, int siz)
{
return recv(fileno_stdin(), buf, siz, 0);
}
#else
# if defined(__TANDEM)
# if defined(OPENSSL_TANDEM_FLOSS)
# include <floss.h(floss_read)>
# endif
# endif
int raw_read_stdin(void *buf, int siz)
{
return read(fileno_stdin(), buf, siz);
}
#endif
#if defined(_WIN32) && defined(STD_OUTPUT_HANDLE)
int raw_write_stdout(const void *buf, int siz)
{
DWORD n;
if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, siz, &n, NULL))
return n;
else
return -1;
}
#elif defined(OPENSSL_SYS_TANDEM) && defined(OPENSSL_THREADS) && defined(_SPT_MODEL_)
# if defined(__TANDEM)
# if defined(OPENSSL_TANDEM_FLOSS)
# include <floss.h(floss_write)>
# endif
# endif
int raw_write_stdout(const void *buf,int siz)
{
return write(fileno(stdout),(void*)buf,siz);
}
#else
# if defined(__TANDEM)
# if defined(OPENSSL_TANDEM_FLOSS)
# include <floss.h(floss_write)>
# endif
# endif
int raw_write_stdout(const void *buf, int siz)
{
return write(fileno_stdout(), buf, siz);
}
#endif
/*
* Centralized handling of input and output files with format specification
* The format is meant to show what the input and output is supposed to be,
* and is therefore a show of intent more than anything else. However, it
* does impact behavior on some platforms, such as differentiating between
* text and binary input/output on non-Unix platforms
*/
BIO *dup_bio_in(int format)
{
return BIO_new_fp(stdin,
BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0));
}
BIO *dup_bio_out(int format)
{
BIO *b = BIO_new_fp(stdout,
BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0));
void *prefix = NULL;
if (b == NULL)
return NULL;
#ifdef OPENSSL_SYS_VMS
if (FMT_istext(format))
b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
#endif
if (FMT_istext(format)
&& (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) {
b = BIO_push(BIO_new(BIO_f_prefix()), b);
BIO_set_prefix(b, prefix);
}
return b;
}
BIO *dup_bio_err(int format)
{
BIO *b = BIO_new_fp(stderr,
BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0));
#ifdef OPENSSL_SYS_VMS
if (b != NULL && FMT_istext(format))
b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
#endif
return b;
}
void unbuffer(FILE *fp)
{
/*
* On VMS, setbuf() will only take 32-bit pointers, and a compilation
* with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here.
* However, we trust that the C RTL will never give us a FILE pointer
* above the first 4 GB of memory, so we simply turn off the warning
* temporarily.
*/
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma environment save
# pragma message disable maylosedata2
#endif
setbuf(fp, NULL);
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma environment restore
#endif
}
static const char *modestr(char mode, int format)
{
OPENSSL_assert(mode == 'a' || mode == 'r' || mode == 'w');
switch (mode) {
case 'a':
return FMT_istext(format) ? "a" : "ab";
case 'r':
return FMT_istext(format) ? "r" : "rb";
case 'w':
return FMT_istext(format) ? "w" : "wb";
}
/* The assert above should make sure we never reach this point */
return NULL;
}
static const char *modeverb(char mode)
{
switch (mode) {
case 'a':
return "appending";
case 'r':
return "reading";
case 'w':
return "writing";
}
return "(doing something)";
}
/*
* Open a file for writing, owner-read-only.
*/
BIO *bio_open_owner(const char *filename, int format, int private)
{
FILE *fp = NULL;
BIO *b = NULL;
int textmode, bflags;
#ifndef OPENSSL_NO_POSIX_IO
int fd = -1, mode;
#endif
if (!private || filename == NULL || strcmp(filename, "-") == 0)
return bio_open_default(filename, 'w', format);
textmode = FMT_istext(format);
#ifndef OPENSSL_NO_POSIX_IO
mode = O_WRONLY;
# ifdef O_CREAT
mode |= O_CREAT;
# endif
# ifdef O_TRUNC
mode |= O_TRUNC;
# endif
if (!textmode) {
# ifdef O_BINARY
mode |= O_BINARY;
# elif defined(_O_BINARY)
mode |= _O_BINARY;
# endif
}
# ifdef OPENSSL_SYS_VMS
/* VMS doesn't have O_BINARY, it just doesn't make sense. But,
* it still needs to know that we're going binary, or fdopen()
* will fail with "invalid argument"... so we tell VMS what the
* context is.
*/
if (!textmode)
fd = open(filename, mode, 0600, "ctx=bin");
else
# endif
fd = open(filename, mode, 0600);
if (fd < 0)
goto err;
fp = fdopen(fd, modestr('w', format));
#else /* OPENSSL_NO_POSIX_IO */
/* Have stdio but not Posix IO, do the best we can */
fp = fopen(filename, modestr('w', format));
#endif /* OPENSSL_NO_POSIX_IO */
if (fp == NULL)
goto err;
bflags = BIO_CLOSE;
if (textmode)
bflags |= BIO_FP_TEXT;
b = BIO_new_fp(fp, bflags);
if (b != NULL)
return b;
err:
BIO_printf(bio_err, "%s: Can't open \"%s\" for writing, %s\n",
opt_getprog(), filename, strerror(errno));
ERR_print_errors(bio_err);
/* If we have fp, then fdopen took over fd, so don't close both. */
if (fp != NULL)
fclose(fp);
#ifndef OPENSSL_NO_POSIX_IO
else if (fd >= 0)
close(fd);
#endif
return NULL;
}
static BIO *bio_open_default_(const char *filename, char mode, int format,
int quiet)
{
BIO *ret;
if (filename == NULL || strcmp(filename, "-") == 0) {
ret = mode == 'r' ? dup_bio_in(format) : dup_bio_out(format);
if (quiet) {
ERR_clear_error();
return ret;
}
if (ret != NULL)
return ret;
BIO_printf(bio_err,
"Can't open %s, %s\n",
mode == 'r' ? "stdin" : "stdout", strerror(errno));
} else {
ret = BIO_new_file(filename, modestr(mode, format));
if (quiet) {
ERR_clear_error();
return ret;
}
if (ret != NULL)
return ret;
BIO_printf(bio_err,
"Can't open \"%s\" for %s, %s\n",
filename, modeverb(mode), strerror(errno));
}
ERR_print_errors(bio_err);
return NULL;
}
BIO *bio_open_default(const char *filename, char mode, int format)
{
return bio_open_default_(filename, mode, format, 0);
}
BIO *bio_open_default_quiet(const char *filename, char mode, int format)
{
return bio_open_default_(filename, mode, format, 1);
}
void wait_for_async(SSL *s)
{
/* On Windows select only works for sockets, so we simply don't wait */
#ifndef OPENSSL_SYS_WINDOWS
int width = 0;
fd_set asyncfds;
OSSL_ASYNC_FD *fds;
size_t numfds;
size_t i;
if (!SSL_get_all_async_fds(s, NULL, &numfds))
return;
if (numfds == 0)
return;
fds = app_malloc(sizeof(OSSL_ASYNC_FD) * numfds, "allocate async fds");
if (!SSL_get_all_async_fds(s, fds, &numfds)) {
OPENSSL_free(fds);
return;
}
FD_ZERO(&asyncfds);
for (i = 0; i < numfds; i++) {
if (width <= (int)fds[i])
width = (int)fds[i] + 1;
openssl_fdset((int)fds[i], &asyncfds);
}
select(width, (void *)&asyncfds, NULL, NULL, NULL);
OPENSSL_free(fds);
#endif
}
/* if OPENSSL_SYS_WINDOWS is defined then so is OPENSSL_SYS_MSDOS */
#if defined(OPENSSL_SYS_MSDOS)
int has_stdin_waiting(void)
{
# if defined(OPENSSL_SYS_WINDOWS)
HANDLE inhand = GetStdHandle(STD_INPUT_HANDLE);
DWORD events = 0;
INPUT_RECORD inputrec;
DWORD insize = 1;
BOOL peeked;
if (inhand == INVALID_HANDLE_VALUE) {
return 0;
}
peeked = PeekConsoleInput(inhand, &inputrec, insize, &events);
if (!peeked) {
/* Probably redirected input? _kbhit() does not work in this case */
if (!feof(stdin)) {
return 1;
}
return 0;
}
# endif
return _kbhit();
}
#endif
/* Corrupt a signature by modifying final byte */
void corrupt_signature(const ASN1_STRING *signature)
{
unsigned char *s = signature->data;
s[signature->length - 1] ^= 0x1;
}
int set_cert_times(X509 *x, const char *startdate, const char *enddate,
int days)
{
if (startdate == NULL || strcmp(startdate, "today") == 0) {
if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL)
return 0;
} else {
if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate))
return 0;
}
if (enddate == NULL) {
if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL)
== NULL)
return 0;
} else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) {
return 0;
}
return 1;
}
int set_crl_lastupdate(X509_CRL *crl, const char *lastupdate)
{
int ret = 0;
ASN1_TIME *tm = ASN1_TIME_new();
if (tm == NULL)
goto end;
if (lastupdate == NULL) {
if (X509_gmtime_adj(tm, 0) == NULL)
goto end;
} else {
if (!ASN1_TIME_set_string_X509(tm, lastupdate))
goto end;
}
if (!X509_CRL_set1_lastUpdate(crl, tm))
goto end;
ret = 1;
end:
ASN1_TIME_free(tm);
return ret;
}
int set_crl_nextupdate(X509_CRL *crl, const char *nextupdate,
long days, long hours, long secs)
{
int ret = 0;
ASN1_TIME *tm = ASN1_TIME_new();
if (tm == NULL)
goto end;
if (nextupdate == NULL) {
if (X509_time_adj_ex(tm, days, hours * 60 * 60 + secs, NULL) == NULL)
goto end;
} else {
if (!ASN1_TIME_set_string_X509(tm, nextupdate))
goto end;
}
if (!X509_CRL_set1_nextUpdate(crl, tm))
goto end;
ret = 1;
end:
ASN1_TIME_free(tm);
return ret;
}
void make_uppercase(char *string)
{
int i;
for (i = 0; string[i] != '\0'; i++)
string[i] = toupper((unsigned char)string[i]);
}
/* This function is defined here due to visibility of bio_err */
int opt_printf_stderr(const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = BIO_vprintf(bio_err, fmt, ap);
va_end(ap);
return ret;
}
OSSL_PARAM *app_params_new_from_opts(STACK_OF(OPENSSL_STRING) *opts,
const OSSL_PARAM *paramdefs)
{
OSSL_PARAM *params = NULL;
size_t sz = (size_t)sk_OPENSSL_STRING_num(opts);
size_t params_n;
char *opt = "", *stmp, *vtmp = NULL;
int found = 1;
if (opts == NULL)
return NULL;
params = OPENSSL_zalloc(sizeof(OSSL_PARAM) * (sz + 1));
if (params == NULL)
return NULL;
for (params_n = 0; params_n < sz; params_n++) {
opt = sk_OPENSSL_STRING_value(opts, (int)params_n);
if ((stmp = OPENSSL_strdup(opt)) == NULL
|| (vtmp = strchr(stmp, ':')) == NULL)
goto err;
/* Replace ':' with 0 to terminate the string pointed to by stmp */
*vtmp = 0;
/* Skip over the separator so that vmtp points to the value */
vtmp++;
if (!OSSL_PARAM_allocate_from_text(&params[params_n], paramdefs,
stmp, vtmp, strlen(vtmp), &found))
goto err;
OPENSSL_free(stmp);
}
params[params_n] = OSSL_PARAM_construct_end();
return params;
err:
OPENSSL_free(stmp);
BIO_printf(bio_err, "Parameter %s '%s'\n", found ? "error" : "unknown",
opt);
ERR_print_errors(bio_err);
app_params_free(params);
return NULL;
}
void app_params_free(OSSL_PARAM *params)
{
int i;
if (params != NULL) {
for (i = 0; params[i].key != NULL; ++i)
OPENSSL_free(params[i].data);
OPENSSL_free(params);
}
}
EVP_PKEY *app_keygen(EVP_PKEY_CTX *ctx, const char *alg, int bits, int verbose)
{
EVP_PKEY *res = NULL;
if (verbose && alg != NULL) {
BIO_printf(bio_err, "Generating %s key", alg);
if (bits > 0)
BIO_printf(bio_err, " with %d bits\n", bits);
else
BIO_printf(bio_err, "\n");
}
if (!RAND_status())
BIO_printf(bio_err, "Warning: generating random key material may take a long time\n"
"if the system has a poor entropy source\n");
if (EVP_PKEY_keygen(ctx, &res) <= 0)
app_bail_out("%s: Error generating %s key\n", opt_getprog(),
alg != NULL ? alg : "asymmetric");
return res;
}
EVP_PKEY *app_paramgen(EVP_PKEY_CTX *ctx, const char *alg)
{
EVP_PKEY *res = NULL;
if (!RAND_status())
BIO_printf(bio_err, "Warning: generating random key parameters may take a long time\n"
"if the system has a poor entropy source\n");
if (EVP_PKEY_paramgen(ctx, &res) <= 0)
app_bail_out("%s: Generating %s key parameters failed\n",
opt_getprog(), alg != NULL ? alg : "asymmetric");
return res;
}
/*
* Return non-zero if the legacy path is still an option.
* This decision is based on the global command line operations and the
* behaviour thus far.
*/
int opt_legacy_okay(void)
{
int provider_options = opt_provider_option_given();
int libctx = app_get0_libctx() != NULL || app_get0_propq() != NULL;
/*
* Having a provider option specified or a custom library context or
* property query, is a sure sign we're not using legacy.
*/
if (provider_options || libctx)
return 0;
return 1;
}
diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c
index b37f3dd3d89c..637bd1d0b7a4 100644
--- a/apps/lib/cmp_mock_srv.c
+++ b/apps/lib/cmp_mock_srv.c
@@ -1,450 +1,452 @@
/*
- * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-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 atf
* https://www.openssl.org/source/license.html
*/
#include "apps.h"
#include "cmp_mock_srv.h"
#include <openssl/cmp.h>
#include <openssl/err.h>
#include <openssl/cmperr.h>
-
+
/* the context for the CMP mock server */
typedef struct
{
X509 *certOut; /* certificate to be returned in cp/ip/kup msg */
STACK_OF(X509) *chainOut; /* chain of certOut to add to extraCerts field */
STACK_OF(X509) *caPubsOut; /* certs to return in caPubs field of ip msg */
OSSL_CMP_PKISI *statusOut; /* status for ip/cp/kup/rp msg unless polling */
- int sendError; /* send error response also on valid requests */
+ int sendError; /* send error response on given request type */
OSSL_CMP_MSG *certReq; /* ir/cr/p10cr/kur remembered while polling */
- int certReqId; /* id of last ir/cr/kur, used for polling */
int pollCount; /* number of polls before actual cert response */
int curr_pollCount; /* number of polls so far for current request */
int checkAfterTime; /* time the client should wait between polling */
} mock_srv_ctx;
static void mock_srv_ctx_free(mock_srv_ctx *ctx)
{
if (ctx == NULL)
return;
OSSL_CMP_PKISI_free(ctx->statusOut);
X509_free(ctx->certOut);
sk_X509_pop_free(ctx->chainOut, X509_free);
sk_X509_pop_free(ctx->caPubsOut, X509_free);
OSSL_CMP_MSG_free(ctx->certReq);
OPENSSL_free(ctx);
}
static mock_srv_ctx *mock_srv_ctx_new(void)
{
mock_srv_ctx *ctx = OPENSSL_zalloc(sizeof(mock_srv_ctx));
if (ctx == NULL)
goto err;
if ((ctx->statusOut = OSSL_CMP_PKISI_new()) == NULL)
goto err;
- ctx->certReqId = -1;
+ ctx->sendError = -1;
/* all other elements are initialized to 0 or NULL, respectively */
return ctx;
err:
mock_srv_ctx_free(ctx);
return NULL;
}
int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (cert == NULL || X509_up_ref(cert)) {
X509_free(ctx->certOut);
ctx->certOut = cert;
return 1;
}
return 0;
}
int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
STACK_OF(X509) *chain)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
STACK_OF(X509) *chain_copy = NULL;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (chain != NULL && (chain_copy = X509_chain_up_ref(chain)) == NULL)
return 0;
sk_X509_pop_free(ctx->chainOut, X509_free);
ctx->chainOut = chain_copy;
return 1;
}
int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
STACK_OF(X509) *caPubs)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
STACK_OF(X509) *caPubs_copy = NULL;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (caPubs != NULL && (caPubs_copy = X509_chain_up_ref(caPubs)) == NULL)
return 0;
sk_X509_pop_free(ctx->caPubsOut, X509_free);
ctx->caPubsOut = caPubs_copy;
return 1;
}
int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
int fail_info, const char *text)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
OSSL_CMP_PKISI *si;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, text)) == NULL)
return 0;
OSSL_CMP_PKISI_free(ctx->statusOut);
ctx->statusOut = si;
return 1;
}
-int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val)
+int ossl_cmp_mock_srv_set_sendError(OSSL_CMP_SRV_CTX *srv_ctx, int bodytype)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
- ctx->sendError = val != 0;
+ /* might check bodytype, but this would require exporting all body types */
+ ctx->sendError = bodytype;
return 1;
}
int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (count < 0) {
ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
return 0;
}
ctx->pollCount = count;
return 1;
}
int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx->checkAfterTime = sec;
return 1;
}
static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *cert_req,
- int certReqId,
+ ossl_unused int certReqId,
const OSSL_CRMF_MSG *crm,
const X509_REQ *p10cr,
X509 **certOut,
STACK_OF(X509) **chainOut,
STACK_OF(X509) **caPubs)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
OSSL_CMP_PKISI *si = NULL;
if (ctx == NULL || cert_req == NULL
|| certOut == NULL || chainOut == NULL || caPubs == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
- if (ctx->sendError) {
+ if (ctx->sendError == 1
+ || ctx->sendError == OSSL_CMP_MSG_get_bodytype(cert_req)) {
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
return NULL;
}
*certOut = NULL;
*chainOut = NULL;
*caPubs = NULL;
- ctx->certReqId = certReqId;
if (ctx->pollCount > 0 && ctx->curr_pollCount == 0) {
/* start polling */
if (ctx->certReq != NULL) {
/* already in polling mode */
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
return NULL;
}
if ((ctx->certReq = OSSL_CMP_MSG_dup(cert_req)) == NULL)
return NULL;
return OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL);
}
if (ctx->curr_pollCount >= ctx->pollCount)
/* give final response after polling */
ctx->curr_pollCount = 0;
if (OSSL_CMP_MSG_get_bodytype(cert_req) == OSSL_CMP_KUR
&& crm != NULL && ctx->certOut != NULL) {
const OSSL_CRMF_CERTID *cid = OSSL_CRMF_MSG_get0_regCtrl_oldCertID(crm);
const X509_NAME *issuer = X509_get_issuer_name(ctx->certOut);
const ASN1_INTEGER *serial = X509_get0_serialNumber(ctx->certOut);
if (cid == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_CERTID);
return NULL;
}
if (issuer != NULL
&& X509_NAME_cmp(issuer, OSSL_CRMF_CERTID_get0_issuer(cid)) != 0) {
ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID);
return NULL;
}
if (serial != NULL
&& ASN1_INTEGER_cmp(serial,
OSSL_CRMF_CERTID_get0_serialNumber(cid)) != 0) {
ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID);
return NULL;
}
}
if (ctx->certOut != NULL
&& (*certOut = X509_dup(ctx->certOut)) == NULL)
goto err;
if (ctx->chainOut != NULL
&& (*chainOut = X509_chain_up_ref(ctx->chainOut)) == NULL)
goto err;
if (ctx->caPubsOut != NULL
&& (*caPubs = X509_chain_up_ref(ctx->caPubsOut)) == NULL)
goto err;
if (ctx->statusOut != NULL
&& (si = OSSL_CMP_PKISI_dup(ctx->statusOut)) == NULL)
goto err;
return si;
err:
X509_free(*certOut);
*certOut = NULL;
sk_X509_pop_free(*chainOut, X509_free);
*chainOut = NULL;
sk_X509_pop_free(*caPubs, X509_free);
*caPubs = NULL;
return NULL;
}
static OSSL_CMP_PKISI *process_rr(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *rr,
const X509_NAME *issuer,
const ASN1_INTEGER *serial)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
if (ctx == NULL || rr == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
- if (ctx->sendError || ctx->certOut == NULL) {
+ if (ctx->certOut == NULL || ctx->sendError == 1
+ || ctx->sendError == OSSL_CMP_MSG_get_bodytype(rr)) {
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
return NULL;
}
/* Allow any RR derived from CSR, which may include subject and serial */
if (issuer == NULL || serial == NULL)
return OSSL_CMP_PKISI_dup(ctx->statusOut);
/* accept revocation only for the certificate we sent in ir/cr/kur */
if (X509_NAME_cmp(issuer, X509_get_issuer_name(ctx->certOut)) != 0
|| ASN1_INTEGER_cmp(serial,
X509_get0_serialNumber(ctx->certOut)) != 0) {
ERR_raise_data(ERR_LIB_CMP, CMP_R_REQUEST_NOT_ACCEPTED,
"wrong certificate to revoke");
return NULL;
}
return OSSL_CMP_PKISI_dup(ctx->statusOut);
}
static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *genm,
const STACK_OF(OSSL_CMP_ITAV) *in,
STACK_OF(OSSL_CMP_ITAV) **out)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
if (ctx == NULL || genm == NULL || in == NULL || out == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
- if (sk_OSSL_CMP_ITAV_num(in) > 1 || ctx->sendError) {
+ if (ctx->sendError == 1
+ || ctx->sendError == OSSL_CMP_MSG_get_bodytype(genm)
+ || sk_OSSL_CMP_ITAV_num(in) > 1) {
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
return 0;
}
*out = sk_OSSL_CMP_ITAV_deep_copy(in, OSSL_CMP_ITAV_dup,
OSSL_CMP_ITAV_free);
return *out != NULL;
}
static void process_error(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *error,
const OSSL_CMP_PKISI *statusInfo,
const ASN1_INTEGER *errorCode,
const OSSL_CMP_PKIFREETEXT *errorDetails)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
char buf[OSSL_CMP_PKISI_BUFLEN];
char *sibuf;
int i;
if (ctx == NULL || error == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return;
}
BIO_printf(bio_err, "mock server received error:\n");
if (statusInfo == NULL) {
BIO_printf(bio_err, "pkiStatusInfo absent\n");
} else {
sibuf = OSSL_CMP_snprint_PKIStatusInfo(statusInfo, buf, sizeof(buf));
BIO_printf(bio_err, "pkiStatusInfo: %s\n",
sibuf != NULL ? sibuf: "<invalid>");
}
if (errorCode == NULL)
BIO_printf(bio_err, "errorCode absent\n");
else
BIO_printf(bio_err, "errorCode: %ld\n", ASN1_INTEGER_get(errorCode));
if (sk_ASN1_UTF8STRING_num(errorDetails) <= 0) {
BIO_printf(bio_err, "errorDetails absent\n");
} else {
BIO_printf(bio_err, "errorDetails: ");
for (i = 0; i < sk_ASN1_UTF8STRING_num(errorDetails); i++) {
if (i > 0)
BIO_printf(bio_err, ", ");
BIO_printf(bio_err, "\"");
ASN1_STRING_print(bio_err,
sk_ASN1_UTF8STRING_value(errorDetails, i));
BIO_printf(bio_err, "\"");
}
BIO_printf(bio_err, "\n");
}
}
static int process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
- const OSSL_CMP_MSG *certConf, int certReqId,
+ const OSSL_CMP_MSG *certConf,
+ ossl_unused int certReqId,
const ASN1_OCTET_STRING *certHash,
const OSSL_CMP_PKISI *si)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
ASN1_OCTET_STRING *digest;
if (ctx == NULL || certConf == NULL || certHash == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
- if (ctx->sendError || ctx->certOut == NULL) {
+ if (ctx->sendError == 1
+ || ctx->sendError == OSSL_CMP_MSG_get_bodytype(certConf)
+ || ctx->certOut == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
return 0;
}
- if (certReqId != ctx->certReqId) {
- /* in case of error, invalid reqId -1 */
- ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
- return 0;
- }
-
if ((digest = X509_digest_sig(ctx->certOut, NULL, NULL)) == NULL)
return 0;
if (ASN1_OCTET_STRING_cmp(certHash, digest) != 0) {
ASN1_OCTET_STRING_free(digest);
ERR_raise(ERR_LIB_CMP, CMP_R_CERTHASH_UNMATCHED);
return 0;
}
ASN1_OCTET_STRING_free(digest);
return 1;
}
static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
- const OSSL_CMP_MSG *pollReq, int certReqId,
+ const OSSL_CMP_MSG *pollReq,
+ ossl_unused int certReqId,
OSSL_CMP_MSG **certReq, int64_t *check_after)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
if (ctx == NULL || pollReq == NULL
|| certReq == NULL || check_after == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
- if (ctx->sendError) {
+ if (ctx->sendError == 1
+ || ctx->sendError == OSSL_CMP_MSG_get_bodytype(pollReq)) {
*certReq = NULL;
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
return 0;
}
if (ctx->certReq == NULL) {
/* not currently in polling mode */
*certReq = NULL;
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
return 0;
}
if (++ctx->curr_pollCount >= ctx->pollCount) {
/* end polling */
*certReq = ctx->certReq;
ctx->certReq = NULL;
*check_after = 0;
} else {
*certReq = NULL;
*check_after = ctx->checkAfterTime;
}
return 1;
}
OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq)
{
OSSL_CMP_SRV_CTX *srv_ctx = OSSL_CMP_SRV_CTX_new(libctx, propq);
mock_srv_ctx *ctx = mock_srv_ctx_new();
if (srv_ctx != NULL && ctx != NULL
&& OSSL_CMP_SRV_CTX_init(srv_ctx, ctx, process_cert_request,
process_rr, process_genm, process_error,
process_certConf, process_pollReq))
return srv_ctx;
mock_srv_ctx_free(ctx);
OSSL_CMP_SRV_CTX_free(srv_ctx);
return NULL;
}
void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx)
{
if (srv_ctx != NULL)
mock_srv_ctx_free(OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx));
OSSL_CMP_SRV_CTX_free(srv_ctx);
}
diff --git a/apps/openssl.cnf b/apps/openssl.cnf
index 03330e0120a2..12bc40896ef2 100644
--- a/apps/openssl.cnf
+++ b/apps/openssl.cnf
@@ -1,390 +1,390 @@
#
# OpenSSL example configuration file.
# See doc/man5/config.pod for more info.
#
# This is mostly being used for generation of certificate requests,
# but may be used for auto loading of providers
# Note that you can include other files from the main configuration
# file using the .include directive.
#.include filename
# This definition stops the following lines choking if HOME isn't
# defined.
HOME = .
# Use this in order to automatically load providers.
openssl_conf = openssl_init
# Comment out the next line to ignore configuration errors
config_diagnostics = 1
# Extra OBJECT IDENTIFIER info:
# oid_file = $ENV::HOME/.oid
oid_section = new_oids
# To use this configuration file with the "-extfile" option of the
# "openssl x509" utility, name here the section containing the
# X.509v3 extensions to use:
# extensions =
# (Alternatively, use a configuration file that has only
# X.509v3 extensions in its main [= default] section.)
[ new_oids ]
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
# Add a simple OID like this:
# testoid1=1.2.3.4
# Or use config file substitution like this:
# testoid2=${testoid1}.5.6
# Policies used by the TSA examples.
tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7
# For FIPS
# Optionally include a file that is generated by the OpenSSL fipsinstall
# application. This file contains configuration data required by the OpenSSL
# fips provider. It contains a named section e.g. [fips_sect] which is
# referenced from the [provider_sect] below.
# Refer to the OpenSSL security policy for more information.
# .include fipsmodule.cnf
[openssl_init]
providers = provider_sect
# List of providers to load
[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included fipsmodule.cnf.
# fips = fips_sect
# If no providers are activated explicitly, the default one is activated implicitly.
# See man 7 OSSL_PROVIDER-default for more details.
#
# If you add a section explicitly activating any other provider(s), you most
# probably need to explicitly activate the default provider, otherwise it
# becomes unavailable in openssl. As a consequence applications depending on
# OpenSSL may not work correctly which could lead to significant system
# problems including inability to remotely access the system.
[default_sect]
# activate = 1
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = ./demoCA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several certs with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.
certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key
x509_extensions = usr_cert # The extensions to add to the cert
# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
# Extension copying option: use with caution.
# copy_extensions = copy
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions = crl_ext
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = default # use public key default MD
preserve = no # keep passed DN ordering
# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy = policy_match
# For the CA policy
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extensions to add to the self signed cert
# Passwords for private keys if not present they will be prompted for
# input_password = secret
# output_password = secret
# This sets a mask for permitted string types. There are several options.
# default: PrintableString, T61String, BMPString.
# pkix : PrintableString, BMPString (PKIX recommendation before 2004)
# utf8only: only UTF8Strings (PKIX recommendation after 2004).
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
# MASK:XXXX a literal mask value.
# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
string_mask = utf8only
# req_extensions = v3_req # The extensions to add to a certificate request
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Some-State
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Internet Widgits Pty Ltd
# we can do this but it is not needed normally :-)
#1.organizationName = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd
organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default =
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
# SET-ex3 = SET extension number 3
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[ usr_cert ]
# These extensions are added when 'ca' signs a request.
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints=CA:FALSE
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move
# Copy subject details
# issuerAltName=issuer:copy
# This is required for TSA certificates.
# extendedKeyUsage = critical,timeStamping
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[ v3_ca ]
# Extensions for a typical CA
# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true
# Key usage: this is typical for a CA certificate. However since it will
# prevent it being used as an test self-signed certificate it is best
# left out by default.
# keyUsage = cRLSign, keyCertSign
# Include email address in subject alt name: another PKIX recommendation
# subjectAltName=email:copy
# Copy issuer details
# issuerAltName=issuer:copy
# DER hex encoding of an extension: beware experts only!
# obj=DER:02:03
# Where 'obj' is a standard or added object
# You can even override a supported extension:
# basicConstraints= critical, DER:30:03:01:01:FF
[ crl_ext ]
# CRL extensions.
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always
[ proxy_cert_ext ]
# These extensions should be added when creating a proxy certificate
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints=CA:FALSE
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move
# Copy subject details
# issuerAltName=issuer:copy
# This really needs to be in place for it to be a proxy certificate.
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
####################################################################
[ tsa ]
default_tsa = tsa_config1 # the default TSA section
[ tsa_config1 ]
# These are used by the TSA reply generation only.
dir = ./demoCA # TSA root directory
serial = $dir/tsaserial # The current serial number (mandatory)
crypto_device = builtin # OpenSSL engine to use for signing
signer_cert = $dir/tsacert.pem # The TSA signing certificate
# (optional)
certs = $dir/cacert.pem # Certificate chain to include in reply
# (optional)
signer_key = $dir/private/tsakey.pem # The TSA private key (optional)
signer_digest = sha256 # Signing digest to use. (Optional)
default_policy = tsa_policy1 # Policy if request did not specify it
# (optional)
other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional)
digests = sha1, sha256, sha384, sha512 # Acceptable message digests (mandatory)
accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
clock_precision_digits = 0 # number of digits after dot. (optional)
ordering = yes # Is ordering defined for timestamps?
# (optional, default: no)
tsa_name = yes # Must the TSA name be included in the reply?
# (optional, default: no)
ess_cert_id_chain = no # Must the ESS cert id chain be included?
# (optional, default: no)
ess_cert_id_alg = sha1 # algorithm to compute certificate
# identifier (optional, default: sha1)
[insta] # CMP using Insta Demo CA
# Message transfer
server = pki.certificate.fi:8700
# proxy = # set this as far as needed, e.g., http://192.168.1.1:8080
# tls_use = 0
path = pkix/
# Server authentication
recipient = "/C=FI/O=Insta Demo/CN=Insta Demo CA" # or set srvcert or issuer
ignore_keyusage = 1 # potentially needed quirk
unprotected_errors = 1 # potentially needed quirk
extracertsout = insta.extracerts.pem
# Client authentication
ref = 3078 # user identification
secret = pass:insta # can be used for both client and server side
# Generic message options
cmd = ir # default operation, can be overridden on cmd line with, e.g., kur
# Certificate enrollment
subject = "/CN=openssl-cmp-test"
newkey = insta.priv.pem
-out_trusted = insta.ca.crt
+out_trusted = apps/insta.ca.crt # does not include keyUsage digitalSignature
certout = insta.cert.pem
[pbm] # Password-based protection for Insta CA
# Server and client authentication
ref = $insta::ref # 3078
secret = $insta::secret # pass:insta
[signature] # Signature-based protection for Insta CA
# Server authentication
-trusted = insta.ca.crt # does not include keyUsage digitalSignature
+trusted = $insta::out_trusted # apps/insta.ca.crt
# Client authentication
secret = # disable PBM
key = $insta::newkey # insta.priv.pem
cert = $insta::certout # insta.cert.pem
[ir]
cmd = ir
[cr]
cmd = cr
[kur]
# Certificate update
cmd = kur
oldcert = $insta::certout # insta.cert.pem
[rr]
# Certificate revocation
cmd = rr
oldcert = $insta::certout # insta.cert.pem
diff --git a/apps/rehash.c b/apps/rehash.c
index e4a4e14fd497..5c6d5340becf 100644
--- a/apps/rehash.c
+++ b/apps/rehash.c
@@ -1,573 +1,578 @@
/*
- * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
# ifndef NAME_MAX
# define NAME_MAX 255
# 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, buflen, errs = 0;
size_t i;
const char *pathsep;
const char *filename;
char *buf, *copy = NULL;
STACK_OF(OPENSSL_STRING) *files = NULL;
if (app_access(dirname, W_OK) < 0) {
BIO_printf(bio_err, "Skipping %s, can't write\n", dirname);
return 1;
}
buflen = strlen(dirname);
pathsep = (buflen && !ends_with_dirsep(dirname)) ? "/": "";
buflen += NAME_MAX + 1 + 1;
buf = app_malloc(buflen, "filename buffer");
if (verbose)
BIO_printf(bio_out, "Doing %s\n", dirname);
- if ((files = sk_OPENSSL_STRING_new_null()) == NULL) {
+ 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) {
if ((copy = OPENSSL_strdup(filename)) == NULL
|| sk_OPENSSL_STRING_push(files, copy) == 0) {
OPENSSL_free(copy);
BIO_puts(bio_err, "out of memory\n");
errs = 1;
goto err;
}
}
OPENSSL_DIR_end(&d);
sk_OPENSSL_STRING_sort(files);
numfiles = sk_OPENSSL_STRING_num(files);
for (n = 0; n < numfiles; ++n) {
filename = sk_OPENSSL_STRING_value(files, n);
if (BIO_snprintf(buf, buflen, "%s%s%s",
dirname, pathsep, filename) >= buflen)
continue;
if (lstat(buf, &st) < 0)
continue;
if (S_ISLNK(st.st_mode) && handle_symlink(filename, buf) == 0)
continue;
errs += do_file(filename, buf, h);
}
for (i = 0; i < OSSL_NELEM(hash_table); i++) {
for (bp = hash_table[i]; bp; bp = nextbp) {
nextbp = bp->next;
nextid = 0;
memset(idmask, 0, (bp->num_needed + 7) / 8);
for (ep = bp->first_entry; ep; ep = ep->next)
if (ep->old_id < bp->num_needed)
bit_set(idmask, ep->old_id);
for (ep = bp->first_entry; ep; ep = nextep) {
nextep = ep->next;
if (ep->old_id < bp->num_needed) {
/* Link exists, and is used as-is */
BIO_snprintf(buf, buflen, "%08x.%s%d", bp->hash,
suffixes[bp->type], ep->old_id);
if (verbose)
BIO_printf(bio_out, "link %s -> %s\n",
ep->filename, buf);
} else if (ep->need_symlink) {
/* New link needed (it may replace something) */
while (bit_isset(idmask, nextid))
nextid++;
BIO_snprintf(buf, buflen, "%s%s%n%08x.%s%d",
dirname, pathsep, &n, bp->hash,
suffixes[bp->type], nextid);
if (verbose)
BIO_printf(bio_out, "link %s -> %s\n",
ep->filename, &buf[n]);
if (unlink(buf) < 0 && errno != ENOENT) {
BIO_printf(bio_err,
"%s: Can't unlink %s, %s\n",
opt_getprog(), buf, strerror(errno));
errs++;
}
if (symlink(ep->filename, buf) < 0) {
BIO_printf(bio_err,
"%s: Can't symlink %s, %s\n",
opt_getprog(), ep->filename,
strerror(errno));
errs++;
}
bit_set(idmask, nextid);
} else if (remove_links) {
/* Link to be deleted */
BIO_snprintf(buf, buflen, "%s%s%n%08x.%s%d",
dirname, pathsep, &n, bp->hash,
suffixes[bp->type], ep->old_id);
if (verbose)
BIO_printf(bio_out, "unlink %s\n",
&buf[n]);
if (unlink(buf) < 0 && errno != ENOENT) {
BIO_printf(bio_err,
"%s: Can't unlink %s, %s\n",
opt_getprog(), buf, strerror(errno));
errs++;
}
}
OPENSSL_free(ep->filename);
OPENSSL_free(ep);
}
OPENSSL_free(bp);
}
hash_table[i] = NULL;
}
err:
sk_OPENSSL_STRING_pop_free(files, str_free);
OPENSSL_free(buf);
return errs;
}
typedef enum OPTION_choice {
OPT_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);
for (e = strtok(m, lsc); e != NULL; e = strtok(NULL, lsc))
errs += do_dir(e, h);
OPENSSL_free(m);
} else {
errs += do_dir(X509_get_default_cert_dir(), h);
}
end:
return errs;
}
#else
const OPTIONS rehash_options[] = {
{NULL}
};
int rehash_main(int argc, char **argv)
{
BIO_printf(bio_err, "Not available; use c_rehash script\n");
return 1;
}
#endif /* defined(OPENSSL_SYS_UNIX) || defined(__APPLE__) */
diff --git a/apps/s_server.c b/apps/s_server.c
index 2b0b6ba381fb..a203d6a091ca 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -1,3790 +1,3791 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 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 <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(_WIN32)
/* Included before async.h to avoid some warnings */
# include <windows.h>
#endif
#include <openssl/e_os2.h>
#include <openssl/async.h>
#include <openssl/ssl.h>
#include <openssl/decoder.h>
#ifndef OPENSSL_NO_SOCK
/*
* With IPv6, it looks like Digital has mixed up the proper order of
* recursive header file inclusion, resulting in the compiler complaining
* that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is
* needed to have fileno() declared correctly... So let's define u_int
*/
#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT)
# define __U_INT
typedef unsigned int u_int;
#endif
#include <openssl/bn.h>
#include "apps.h"
#include "progs.h"
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>
#include <openssl/rand.h>
#include <openssl/ocsp.h>
#ifndef OPENSSL_NO_DH
# include <openssl/dh.h>
#endif
#include <openssl/rsa.h>
#include "s_apps.h"
#include "timeouts.h"
#ifdef CHARSET_EBCDIC
#include <openssl/ebcdic.h>
#endif
#include "internal/sockets.h"
static int not_resumable_sess_cb(SSL *s, int is_forward_secure);
static int sv_body(int s, int stype, int prot, unsigned char *context);
static int www_body(int s, int stype, int prot, unsigned char *context);
static int rev_body(int s, int stype, int prot, unsigned char *context);
static void close_accept_socket(void);
static int init_ssl_connection(SSL *s);
static void print_stats(BIO *bp, SSL_CTX *ctx);
static int generate_session_id(SSL *ssl, unsigned char *id,
unsigned int *id_len);
static void init_session_cache_ctx(SSL_CTX *sctx);
static void free_sessions(void);
static void print_connection_info(SSL *con);
static const int bufsize = 16 * 1024;
static int accept_socket = -1;
#define TEST_CERT "server.pem"
#define TEST_CERT2 "server2.pem"
static int s_nbio = 0;
static int s_nbio_test = 0;
static int s_crlf = 0;
static SSL_CTX *ctx = NULL;
static SSL_CTX *ctx2 = NULL;
static int www = 0;
static BIO *bio_s_out = NULL;
static BIO *bio_s_msg = NULL;
static int s_debug = 0;
static int s_tlsextdebug = 0;
static int s_msg = 0;
static int s_quiet = 0;
static int s_ign_eof = 0;
static int s_brief = 0;
static char *keymatexportlabel = NULL;
static int keymatexportlen = 20;
static int async = 0;
static int use_sendfile = 0;
static const char *session_id_prefix = NULL;
#ifndef OPENSSL_NO_DTLS
static int enable_timeouts = 0;
static long socket_mtu;
#endif
/*
* We define this but make it always be 0 in no-dtls builds to simplify the
* code.
*/
static int dtlslisten = 0;
static int stateless = 0;
static int early_data = 0;
static SSL_SESSION *psksess = NULL;
static char *psk_identity = "Client_identity";
char *psk_key = NULL; /* by default PSK is not used */
static char http_server_binmode = 0; /* for now: 0/1 = default/binary */
#ifndef OPENSSL_NO_PSK
static unsigned int psk_server_cb(SSL *ssl, const char *identity,
unsigned char *psk,
unsigned int max_psk_len)
{
long key_len = 0;
unsigned char *key;
if (s_debug)
BIO_printf(bio_s_out, "psk_server_cb\n");
if (!SSL_is_dtls(ssl) && SSL_version(ssl) >= TLS1_3_VERSION) {
/*
* This callback is designed for use in (D)TLSv1.2 (or below). It is
* possible to use a single callback for all protocol versions - but it
* is preferred to use a dedicated callback for TLSv1.3. For TLSv1.3 we
* have psk_find_session_cb.
*/
return 0;
}
if (identity == NULL) {
BIO_printf(bio_err, "Error: client did not send PSK identity\n");
goto out_err;
}
if (s_debug)
BIO_printf(bio_s_out, "identity_len=%d identity=%s\n",
(int)strlen(identity), identity);
/* here we could lookup the given identity e.g. from a database */
if (strcmp(identity, psk_identity) != 0) {
BIO_printf(bio_s_out, "PSK warning: client identity not what we expected"
" (got '%s' expected '%s')\n", identity, psk_identity);
} else {
if (s_debug)
BIO_printf(bio_s_out, "PSK client identity found\n");
}
/* convert the PSK key to binary */
key = OPENSSL_hexstr2buf(psk_key, &key_len);
if (key == NULL) {
BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n",
psk_key);
return 0;
}
if (key_len > (int)max_psk_len) {
BIO_printf(bio_err,
"psk buffer of callback is too small (%d) for key (%ld)\n",
max_psk_len, key_len);
OPENSSL_free(key);
return 0;
}
memcpy(psk, key, key_len);
OPENSSL_free(key);
if (s_debug)
BIO_printf(bio_s_out, "fetched PSK len=%ld\n", key_len);
return key_len;
out_err:
if (s_debug)
BIO_printf(bio_err, "Error in PSK server callback\n");
(void)BIO_flush(bio_err);
(void)BIO_flush(bio_s_out);
return 0;
}
#endif
static int psk_find_session_cb(SSL *ssl, const unsigned char *identity,
size_t identity_len, SSL_SESSION **sess)
{
SSL_SESSION *tmpsess = NULL;
unsigned char *key;
long key_len;
const SSL_CIPHER *cipher = NULL;
if (strlen(psk_identity) != identity_len
|| memcmp(psk_identity, identity, identity_len) != 0) {
*sess = NULL;
return 1;
}
if (psksess != NULL) {
SSL_SESSION_up_ref(psksess);
*sess = psksess;
return 1;
}
key = OPENSSL_hexstr2buf(psk_key, &key_len);
if (key == NULL) {
BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n",
psk_key);
return 0;
}
/* We default to SHA256 */
cipher = SSL_CIPHER_find(ssl, tls13_aes128gcmsha256_id);
if (cipher == NULL) {
BIO_printf(bio_err, "Error finding suitable ciphersuite\n");
OPENSSL_free(key);
return 0;
}
tmpsess = SSL_SESSION_new();
if (tmpsess == NULL
|| !SSL_SESSION_set1_master_key(tmpsess, key, key_len)
|| !SSL_SESSION_set_cipher(tmpsess, cipher)
|| !SSL_SESSION_set_protocol_version(tmpsess, SSL_version(ssl))) {
OPENSSL_free(key);
+ SSL_SESSION_free(tmpsess);
return 0;
}
OPENSSL_free(key);
*sess = tmpsess;
return 1;
}
#ifndef OPENSSL_NO_SRP
static srpsrvparm srp_callback_parm;
#endif
static int local_argc = 0;
static char **local_argv;
#ifdef CHARSET_EBCDIC
static int ebcdic_new(BIO *bi);
static int ebcdic_free(BIO *a);
static int ebcdic_read(BIO *b, char *out, int outl);
static int ebcdic_write(BIO *b, const char *in, int inl);
static long ebcdic_ctrl(BIO *b, int cmd, long num, void *ptr);
static int ebcdic_gets(BIO *bp, char *buf, int size);
static int ebcdic_puts(BIO *bp, const char *str);
# define BIO_TYPE_EBCDIC_FILTER (18|0x0200)
static BIO_METHOD *methods_ebcdic = NULL;
/* This struct is "unwarranted chumminess with the compiler." */
typedef struct {
size_t alloced;
char buff[1];
} EBCDIC_OUTBUFF;
static const BIO_METHOD *BIO_f_ebcdic_filter()
{
if (methods_ebcdic == NULL) {
methods_ebcdic = BIO_meth_new(BIO_TYPE_EBCDIC_FILTER,
"EBCDIC/ASCII filter");
if (methods_ebcdic == NULL
|| !BIO_meth_set_write(methods_ebcdic, ebcdic_write)
|| !BIO_meth_set_read(methods_ebcdic, ebcdic_read)
|| !BIO_meth_set_puts(methods_ebcdic, ebcdic_puts)
|| !BIO_meth_set_gets(methods_ebcdic, ebcdic_gets)
|| !BIO_meth_set_ctrl(methods_ebcdic, ebcdic_ctrl)
|| !BIO_meth_set_create(methods_ebcdic, ebcdic_new)
|| !BIO_meth_set_destroy(methods_ebcdic, ebcdic_free))
return NULL;
}
return methods_ebcdic;
}
static int ebcdic_new(BIO *bi)
{
EBCDIC_OUTBUFF *wbuf;
wbuf = app_malloc(sizeof(*wbuf) + 1024, "ebcdic wbuf");
wbuf->alloced = 1024;
wbuf->buff[0] = '\0';
BIO_set_data(bi, wbuf);
BIO_set_init(bi, 1);
return 1;
}
static int ebcdic_free(BIO *a)
{
EBCDIC_OUTBUFF *wbuf;
if (a == NULL)
return 0;
wbuf = BIO_get_data(a);
OPENSSL_free(wbuf);
BIO_set_data(a, NULL);
BIO_set_init(a, 0);
return 1;
}
static int ebcdic_read(BIO *b, char *out, int outl)
{
int ret = 0;
BIO *next = BIO_next(b);
if (out == NULL || outl == 0)
return 0;
if (next == NULL)
return 0;
ret = BIO_read(next, out, outl);
if (ret > 0)
ascii2ebcdic(out, out, ret);
return ret;
}
static int ebcdic_write(BIO *b, const char *in, int inl)
{
EBCDIC_OUTBUFF *wbuf;
BIO *next = BIO_next(b);
int ret = 0;
int num;
if ((in == NULL) || (inl <= 0))
return 0;
if (next == NULL)
return 0;
wbuf = (EBCDIC_OUTBUFF *) BIO_get_data(b);
if (inl > (num = wbuf->alloced)) {
num = num + num; /* double the size */
if (num < inl)
num = inl;
OPENSSL_free(wbuf);
wbuf = app_malloc(sizeof(*wbuf) + num, "grow ebcdic wbuf");
wbuf->alloced = num;
wbuf->buff[0] = '\0';
BIO_set_data(b, wbuf);
}
ebcdic2ascii(wbuf->buff, in, inl);
ret = BIO_write(next, wbuf->buff, inl);
return ret;
}
static long ebcdic_ctrl(BIO *b, int cmd, long num, void *ptr)
{
long ret;
BIO *next = BIO_next(b);
if (next == NULL)
return 0;
switch (cmd) {
case BIO_CTRL_DUP:
ret = 0L;
break;
default:
ret = BIO_ctrl(next, cmd, num, ptr);
break;
}
return ret;
}
static int ebcdic_gets(BIO *bp, char *buf, int size)
{
int i, ret = 0;
BIO *next = BIO_next(bp);
if (next == NULL)
return 0;
/* return(BIO_gets(bp->next_bio,buf,size));*/
for (i = 0; i < size - 1; ++i) {
ret = ebcdic_read(bp, &buf[i], 1);
if (ret <= 0)
break;
else if (buf[i] == '\n') {
++i;
break;
}
}
if (i < size)
buf[i] = '\0';
return (ret < 0 && i == 0) ? ret : i;
}
static int ebcdic_puts(BIO *bp, const char *str)
{
if (BIO_next(bp) == NULL)
return 0;
return ebcdic_write(bp, str, strlen(str));
}
#endif
/* This is a context that we pass to callbacks */
typedef struct tlsextctx_st {
char *servername;
BIO *biodebug;
int extension_error;
} tlsextctx;
static int ssl_servername_cb(SSL *s, int *ad, void *arg)
{
tlsextctx *p = (tlsextctx *) arg;
const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
if (servername != NULL && p->biodebug != NULL) {
const char *cp = servername;
unsigned char uc;
BIO_printf(p->biodebug, "Hostname in TLS extension: \"");
while ((uc = *cp++) != 0)
BIO_printf(p->biodebug,
(((uc) & ~127) == 0) && isprint(uc) ? "%c" : "\\x%02x", uc);
BIO_printf(p->biodebug, "\"\n");
}
if (p->servername == NULL)
return SSL_TLSEXT_ERR_NOACK;
if (servername != NULL) {
if (OPENSSL_strcasecmp(servername, p->servername))
return p->extension_error;
if (ctx2 != NULL) {
BIO_printf(p->biodebug, "Switching server context.\n");
SSL_set_SSL_CTX(s, ctx2);
}
}
return SSL_TLSEXT_ERR_OK;
}
/* Structure passed to cert status callback */
typedef struct tlsextstatusctx_st {
int timeout;
/* File to load OCSP Response from (or NULL if no file) */
char *respin;
/* Default responder to use */
char *host, *path, *port;
char *proxy, *no_proxy;
int use_ssl;
int verbose;
} tlsextstatusctx;
static tlsextstatusctx tlscstatp = { -1 };
#ifndef OPENSSL_NO_OCSP
/*
* Helper function to get an OCSP_RESPONSE from a responder. This is a
* simplified version. It examines certificates each time and makes one OCSP
* responder query for each request. A full version would store details such as
* the OCSP certificate IDs and minimise the number of OCSP responses by caching
* them until they were considered "expired".
*/
static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
OCSP_RESPONSE **resp)
{
char *host = NULL, *port = NULL, *path = NULL;
char *proxy = NULL, *no_proxy = NULL;
int use_ssl;
STACK_OF(OPENSSL_STRING) *aia = NULL;
X509 *x = NULL;
X509_STORE_CTX *inctx = NULL;
X509_OBJECT *obj;
OCSP_REQUEST *req = NULL;
OCSP_CERTID *id = NULL;
STACK_OF(X509_EXTENSION) *exts;
int ret = SSL_TLSEXT_ERR_NOACK;
int i;
/* Build up OCSP query from server certificate */
x = SSL_get_certificate(s);
aia = X509_get1_ocsp(x);
if (aia != NULL) {
if (!OSSL_HTTP_parse_url(sk_OPENSSL_STRING_value(aia, 0), &use_ssl,
NULL, &host, &port, NULL, &path, NULL, NULL)) {
BIO_puts(bio_err, "cert_status: can't parse AIA URL\n");
goto err;
}
if (srctx->verbose)
BIO_printf(bio_err, "cert_status: AIA URL: %s\n",
sk_OPENSSL_STRING_value(aia, 0));
} else {
if (srctx->host == NULL) {
BIO_puts(bio_err,
"cert_status: no AIA and no default responder URL\n");
goto done;
}
host = srctx->host;
path = srctx->path;
port = srctx->port;
use_ssl = srctx->use_ssl;
}
proxy = srctx->proxy;
no_proxy = srctx->no_proxy;
inctx = X509_STORE_CTX_new();
if (inctx == NULL)
goto err;
if (!X509_STORE_CTX_init(inctx,
SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)),
NULL, NULL))
goto err;
obj = X509_STORE_CTX_get_obj_by_subject(inctx, X509_LU_X509,
X509_get_issuer_name(x));
if (obj == NULL) {
BIO_puts(bio_err, "cert_status: Can't retrieve issuer certificate.\n");
goto done;
}
id = OCSP_cert_to_id(NULL, x, X509_OBJECT_get0_X509(obj));
X509_OBJECT_free(obj);
if (id == NULL)
goto err;
req = OCSP_REQUEST_new();
if (req == NULL)
goto err;
if (!OCSP_request_add0_id(req, id))
goto err;
id = NULL;
/* Add any extensions to the request */
SSL_get_tlsext_status_exts(s, &exts);
for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
if (!OCSP_REQUEST_add_ext(req, ext, -1))
goto err;
}
*resp = process_responder(req, host, port, path, proxy, no_proxy,
use_ssl, NULL /* headers */, srctx->timeout);
if (*resp == NULL) {
BIO_puts(bio_err, "cert_status: error querying responder\n");
goto done;
}
ret = SSL_TLSEXT_ERR_OK;
goto done;
err:
ret = SSL_TLSEXT_ERR_ALERT_FATAL;
done:
/*
* If we parsed aia we need to free; otherwise they were copied and we
* don't
*/
if (aia != NULL) {
OPENSSL_free(host);
OPENSSL_free(path);
OPENSSL_free(port);
X509_email_free(aia);
}
OCSP_CERTID_free(id);
OCSP_REQUEST_free(req);
X509_STORE_CTX_free(inctx);
return ret;
}
/*
* Certificate Status callback. This is called when a client includes a
* certificate status request extension. The response is either obtained from a
* file, or from an OCSP responder.
*/
static int cert_status_cb(SSL *s, void *arg)
{
tlsextstatusctx *srctx = arg;
OCSP_RESPONSE *resp = NULL;
unsigned char *rspder = NULL;
int rspderlen;
int ret = SSL_TLSEXT_ERR_ALERT_FATAL;
if (srctx->verbose)
BIO_puts(bio_err, "cert_status: callback called\n");
if (srctx->respin != NULL) {
BIO *derbio = bio_open_default(srctx->respin, 'r', FORMAT_ASN1);
if (derbio == NULL) {
BIO_puts(bio_err, "cert_status: Cannot open OCSP response file\n");
goto err;
}
resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
BIO_free(derbio);
if (resp == NULL) {
BIO_puts(bio_err, "cert_status: Error reading OCSP response\n");
goto err;
}
} else {
ret = get_ocsp_resp_from_responder(s, srctx, &resp);
if (ret != SSL_TLSEXT_ERR_OK)
goto err;
}
rspderlen = i2d_OCSP_RESPONSE(resp, &rspder);
if (rspderlen <= 0)
goto err;
SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen);
if (srctx->verbose) {
BIO_puts(bio_err, "cert_status: ocsp response sent:\n");
OCSP_RESPONSE_print(bio_err, resp, 2);
}
ret = SSL_TLSEXT_ERR_OK;
err:
if (ret != SSL_TLSEXT_ERR_OK)
ERR_print_errors(bio_err);
OCSP_RESPONSE_free(resp);
return ret;
}
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
/* This is the context that we pass to next_proto_cb */
typedef struct tlsextnextprotoctx_st {
unsigned char *data;
size_t len;
} tlsextnextprotoctx;
static int next_proto_cb(SSL *s, const unsigned char **data,
unsigned int *len, void *arg)
{
tlsextnextprotoctx *next_proto = arg;
*data = next_proto->data;
*len = next_proto->len;
return SSL_TLSEXT_ERR_OK;
}
#endif /* ndef OPENSSL_NO_NEXTPROTONEG */
/* This the context that we pass to alpn_cb */
typedef struct tlsextalpnctx_st {
unsigned char *data;
size_t len;
} tlsextalpnctx;
static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen, void *arg)
{
tlsextalpnctx *alpn_ctx = arg;
if (!s_quiet) {
/* We can assume that |in| is syntactically valid. */
unsigned int i;
BIO_printf(bio_s_out, "ALPN protocols advertised by the client: ");
for (i = 0; i < inlen;) {
if (i)
BIO_write(bio_s_out, ", ", 2);
BIO_write(bio_s_out, &in[i + 1], in[i]);
i += in[i] + 1;
}
BIO_write(bio_s_out, "\n", 1);
}
if (SSL_select_next_proto
((unsigned char **)out, outlen, alpn_ctx->data, alpn_ctx->len, in,
inlen) != OPENSSL_NPN_NEGOTIATED) {
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
if (!s_quiet) {
BIO_printf(bio_s_out, "ALPN protocols selected: ");
BIO_write(bio_s_out, *out, *outlen);
BIO_write(bio_s_out, "\n", 1);
}
return SSL_TLSEXT_ERR_OK;
}
static int not_resumable_sess_cb(SSL *s, int is_forward_secure)
{
/* disable resumption for sessions with forward secure ciphers */
return is_forward_secure;
}
typedef enum OPTION_choice {
OPT_COMMON,
OPT_ENGINE,
OPT_4, OPT_6, OPT_ACCEPT, OPT_PORT, OPT_UNIX, OPT_UNLINK, OPT_NACCEPT,
OPT_VERIFY, OPT_NAMEOPT, OPT_UPPER_V_VERIFY, OPT_CONTEXT, OPT_CERT, OPT_CRL,
OPT_CRL_DOWNLOAD, OPT_SERVERINFO, OPT_CERTFORM, OPT_KEY, OPT_KEYFORM,
OPT_PASS, OPT_CERT_CHAIN, OPT_DHPARAM, OPT_DCERTFORM, OPT_DCERT,
OPT_DKEYFORM, OPT_DPASS, OPT_DKEY, OPT_DCERT_CHAIN, OPT_NOCERT,
OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, OPT_NO_CACHE,
OPT_EXT_CACHE, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET,
OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE,
OPT_VERIFYCAFILE,
OPT_CASTORE, OPT_NOCASTORE, OPT_CHAINCASTORE, OPT_VERIFYCASTORE,
OPT_NBIO, OPT_NBIO_TEST, OPT_IGN_EOF, OPT_NO_IGN_EOF,
OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_STATUS_VERBOSE,
OPT_STATUS_TIMEOUT, OPT_PROXY, OPT_NO_PROXY, OPT_STATUS_URL,
OPT_STATUS_FILE, OPT_MSG, OPT_MSGFILE,
OPT_TRACE, OPT_SECURITY_DEBUG, OPT_SECURITY_DEBUG_VERBOSE, OPT_STATE,
OPT_CRLF, OPT_QUIET, OPT_BRIEF, OPT_NO_DHE,
OPT_NO_RESUME_EPHEMERAL, OPT_PSK_IDENTITY, OPT_PSK_HINT, OPT_PSK,
OPT_PSK_SESS, OPT_SRPVFILE, OPT_SRPUSERSEED, OPT_REV, OPT_WWW,
OPT_UPPER_WWW, OPT_HTTP, OPT_ASYNC, OPT_SSL_CONFIG,
OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF,
OPT_SSL3, OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1,
OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_LISTEN, OPT_STATELESS,
OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL,
OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN, OPT_SENDFILE,
OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA,
OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, OPT_SCTP_LABEL_BUG,
OPT_HTTP_SERVER_BINMODE, OPT_NOCANAMES, OPT_IGNORE_UNEXPECTED_EOF,
OPT_R_ENUM,
OPT_S_ENUM,
OPT_V_ENUM,
OPT_X_ENUM,
OPT_PROV_ENUM
} OPTION_CHOICE;
const OPTIONS s_server_options[] = {
OPT_SECTION("General"),
{"help", OPT_HELP, '-', "Display this summary"},
{"ssl_config", OPT_SSL_CONFIG, 's',
"Configure SSL_CTX using the given configuration value"},
#ifndef OPENSSL_NO_SSL_TRACE
{"trace", OPT_TRACE, '-', "trace protocol messages"},
#endif
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
OPT_SECTION("Network"),
{"port", OPT_PORT, 'p',
"TCP/IP port to listen on for connections (default is " PORT ")"},
{"accept", OPT_ACCEPT, 's',
"TCP/IP optional host and port to listen on for connections (default is *:" PORT ")"},
#ifdef AF_UNIX
{"unix", OPT_UNIX, 's', "Unix domain socket to accept on"},
{"unlink", OPT_UNLINK, '-', "For -unix, unlink existing socket first"},
#endif
{"4", OPT_4, '-', "Use IPv4 only"},
{"6", OPT_6, '-', "Use IPv6 only"},
OPT_SECTION("Identity"),
{"context", OPT_CONTEXT, 's', "Set session ID context"},
{"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 URI"},
{"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"},
{"verify", OPT_VERIFY, 'n', "Turn on peer certificate verification"},
{"Verify", OPT_UPPER_V_VERIFY, 'n',
"Turn on peer certificate verification, must have a cert"},
{"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
{"cert", OPT_CERT, '<', "Server certificate file to use; default " TEST_CERT},
{"cert2", OPT_CERT2, '<',
"Certificate file to use for servername; default " TEST_CERT2},
{"certform", OPT_CERTFORM, 'F',
"Server certificate file format (PEM/DER/P12); has no effect"},
{"cert_chain", OPT_CERT_CHAIN, '<',
"Server certificate chain file in PEM format"},
{"build_chain", OPT_BUILD_CHAIN, '-', "Build server certificate chain"},
{"serverinfo", OPT_SERVERINFO, 's',
"PEM serverinfo file for certificate"},
{"key", OPT_KEY, 's',
"Private key file to use; default is -cert file or else" TEST_CERT},
{"key2", OPT_KEY2, '<',
"-Private Key file to use for servername if not in -cert2"},
{"keyform", OPT_KEYFORM, 'f', "Key format (ENGINE, other values ignored)"},
{"pass", OPT_PASS, 's', "Private key and cert file pass phrase source"},
{"dcert", OPT_DCERT, '<',
"Second server certificate file to use (usually for DSA)"},
{"dcertform", OPT_DCERTFORM, 'F',
"Second server certificate file format (PEM/DER/P12); has no effect"},
{"dcert_chain", OPT_DCERT_CHAIN, '<',
"second server certificate chain file in PEM format"},
{"dkey", OPT_DKEY, '<',
"Second private key file to use (usually for DSA)"},
{"dkeyform", OPT_DKEYFORM, 'F',
"Second key file format (ENGINE, other values ignored)"},
{"dpass", OPT_DPASS, 's',
"Second private key and cert file pass phrase source"},
{"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"},
{"servername", OPT_SERVERNAME, 's',
"Servername for HostName TLS extension"},
{"servername_fatal", OPT_SERVERNAME_FATAL, '-',
"On servername mismatch send fatal alert (default warning alert)"},
{"nbio_test", OPT_NBIO_TEST, '-', "Test with the non-blocking test bio"},
{"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"},
{"quiet", OPT_QUIET, '-', "No server output"},
{"no_resume_ephemeral", OPT_NO_RESUME_EPHEMERAL, '-',
"Disable caching and tickets if ephemeral (EC)DH is used"},
{"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"},
{"WWW", OPT_UPPER_WWW, '-', "Respond to a 'GET with the file ./path"},
{"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-',
"Do not treat lack of close_notify from a peer as an error"},
{"tlsextdebug", OPT_TLSEXTDEBUG, '-',
"Hex dump of all TLS extensions received"},
{"HTTP", OPT_HTTP, '-', "Like -WWW but ./path includes HTTP headers"},
{"id_prefix", OPT_ID_PREFIX, 's',
"Generate SSL/TLS session IDs prefixed by arg"},
{"keymatexport", OPT_KEYMATEXPORT, 's',
"Export keying material using label"},
{"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
"Export len bytes of keying material; default 20"},
{"CRL", OPT_CRL, '<', "CRL file to use"},
{"CRLform", OPT_CRLFORM, 'F', "CRL file format (PEM or DER); default PEM"},
{"crl_download", OPT_CRL_DOWNLOAD, '-',
"Download CRLs from distribution points in certificate CDP entries"},
{"chainCAfile", OPT_CHAINCAFILE, '<',
"CA file for certificate chain (PEM format)"},
{"chainCApath", OPT_CHAINCAPATH, '/',
"use dir as certificate store path to build CA certificate chain"},
{"chainCAstore", OPT_CHAINCASTORE, ':',
"use URI as certificate store to build CA certificate chain"},
{"verifyCAfile", OPT_VERIFYCAFILE, '<',
"CA file for certificate verification (PEM format)"},
{"verifyCApath", OPT_VERIFYCAPATH, '/',
"use dir as certificate store path to verify CA certificate"},
{"verifyCAstore", OPT_VERIFYCASTORE, ':',
"use URI as certificate store to verify CA certificate"},
{"no_cache", OPT_NO_CACHE, '-', "Disable session cache"},
{"ext_cache", OPT_EXT_CACHE, '-',
"Disable internal cache, set up and use external cache"},
{"verify_return_error", OPT_VERIFY_RET_ERROR, '-',
"Close connection on verification error"},
{"verify_quiet", OPT_VERIFY_QUIET, '-',
"No verify output except verify errors"},
{"ign_eof", OPT_IGN_EOF, '-', "Ignore input EOF (default when -quiet)"},
{"no_ign_eof", OPT_NO_IGN_EOF, '-', "Do not ignore input EOF"},
#ifndef OPENSSL_NO_OCSP
OPT_SECTION("OCSP"),
{"status", OPT_STATUS, '-', "Request certificate status from server"},
{"status_verbose", OPT_STATUS_VERBOSE, '-',
"Print more output in certificate status callback"},
{"status_timeout", OPT_STATUS_TIMEOUT, 'n',
"Status request responder timeout"},
{"status_url", OPT_STATUS_URL, 's', "Status request fallback URL"},
{"proxy", OPT_PROXY, 's',
"[http[s]://]host[:port][/path] of HTTP(S) proxy to use; path is ignored"},
{"no_proxy", OPT_NO_PROXY, 's',
"List of addresses of servers not to use HTTP(S) proxy for"},
{OPT_MORE_STR, 0, 0,
"Default from environment variable 'no_proxy', else 'NO_PROXY', else none"},
{"status_file", OPT_STATUS_FILE, '<',
"File containing DER encoded OCSP Response"},
#endif
OPT_SECTION("Debug"),
{"security_debug", OPT_SECURITY_DEBUG, '-',
"Print output from SSL/TLS security framework"},
{"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-',
"Print more output from SSL/TLS security framework"},
{"brief", OPT_BRIEF, '-',
"Restrict output to brief summary of connection parameters"},
{"rev", OPT_REV, '-',
"act as an echo server that sends back received text reversed"},
{"debug", OPT_DEBUG, '-', "Print more output"},
{"msg", OPT_MSG, '-', "Show protocol messages"},
{"msgfile", OPT_MSGFILE, '>',
"File to send output of -msg or -trace, instead of stdout"},
{"state", OPT_STATE, '-', "Print the SSL states"},
{"async", OPT_ASYNC, '-', "Operate in asynchronous mode"},
{"max_pipelines", OPT_MAX_PIPELINES, 'p',
"Maximum number of encrypt/decrypt pipelines to be used"},
{"naccept", OPT_NACCEPT, 'p', "Terminate after #num connections"},
{"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
OPT_SECTION("Network"),
{"nbio", OPT_NBIO, '-', "Use non-blocking IO"},
{"timeout", OPT_TIMEOUT, '-', "Enable timeouts"},
{"mtu", OPT_MTU, 'p', "Set link-layer MTU"},
{"read_buf", OPT_READ_BUF, 'p',
"Default read buffer size to be used for connections"},
{"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p',
"Size used to split data for encrypt pipelines"},
{"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "},
OPT_SECTION("Server identity"),
{"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity to expect"},
#ifndef OPENSSL_NO_PSK
{"psk_hint", OPT_PSK_HINT, 's', "PSK identity hint to use"},
#endif
{"psk", OPT_PSK, 's', "PSK in hex (without 0x)"},
{"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"},
#ifndef OPENSSL_NO_SRP
{"srpvfile", OPT_SRPVFILE, '<', "(deprecated) The verifier file for SRP"},
{"srpuserseed", OPT_SRPUSERSEED, 's',
"(deprecated) A seed string for a default user salt"},
#endif
OPT_SECTION("Protocol and version"),
{"max_early_data", OPT_MAX_EARLY, 'n',
"The maximum number of bytes of early data as advertised in tickets"},
{"recv_max_early_data", OPT_RECV_MAX_EARLY, 'n',
"The maximum number of bytes of early data (hard limit)"},
{"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"},
{"num_tickets", OPT_S_NUM_TICKETS, 'n',
"The number of TLSv1.3 session tickets that a server will automatically issue" },
{"anti_replay", OPT_ANTI_REPLAY, '-', "Switch on anti-replay protection (default)"},
{"no_anti_replay", OPT_NO_ANTI_REPLAY, '-', "Switch off anti-replay protection"},
{"http_server_binmode", OPT_HTTP_SERVER_BINMODE, '-', "opening files in binary mode when acting as http server (-WWW and -HTTP)"},
{"no_ca_names", OPT_NOCANAMES, '-',
"Disable TLS Extension CA Names"},
{"stateless", OPT_STATELESS, '-', "Require TLSv1.3 cookies"},
#ifndef OPENSSL_NO_SSL3
{"ssl3", OPT_SSL3, '-', "Just talk SSLv3"},
#endif
#ifndef OPENSSL_NO_TLS1
{"tls1", OPT_TLS1, '-', "Just talk TLSv1"},
#endif
#ifndef OPENSSL_NO_TLS1_1
{"tls1_1", OPT_TLS1_1, '-', "Just talk TLSv1.1"},
#endif
#ifndef OPENSSL_NO_TLS1_2
{"tls1_2", OPT_TLS1_2, '-', "just talk TLSv1.2"},
#endif
#ifndef OPENSSL_NO_TLS1_3
{"tls1_3", OPT_TLS1_3, '-', "just talk TLSv1.3"},
#endif
#ifndef OPENSSL_NO_DTLS
{"dtls", OPT_DTLS, '-', "Use any DTLS version"},
{"listen", OPT_LISTEN, '-',
"Listen for a DTLS ClientHello with a cookie and then connect"},
#endif
#ifndef OPENSSL_NO_DTLS1
{"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"},
#endif
#ifndef OPENSSL_NO_DTLS1_2
{"dtls1_2", OPT_DTLS1_2, '-', "Just talk DTLSv1.2"},
#endif
#ifndef OPENSSL_NO_SCTP
{"sctp", OPT_SCTP, '-', "Use SCTP"},
{"sctp_label_bug", OPT_SCTP_LABEL_BUG, '-', "Enable SCTP label length bug"},
#endif
#ifndef OPENSSL_NO_SRTP
{"use_srtp", OPT_SRTP_PROFILES, 's',
"Offer SRTP key management with a colon-separated profile list"},
#endif
{"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"},
#ifndef OPENSSL_NO_NEXTPROTONEG
{"nextprotoneg", OPT_NEXTPROTONEG, 's',
"Set the advertised protocols for the NPN extension (comma-separated list)"},
#endif
{"alpn", OPT_ALPN, 's',
"Set the advertised protocols for the ALPN extension (comma-separated list)"},
#ifndef OPENSSL_NO_KTLS
{"sendfile", OPT_SENDFILE, '-', "Use sendfile to response file with -WWW"},
#endif
OPT_R_OPTIONS,
OPT_S_OPTIONS,
OPT_V_OPTIONS,
OPT_X_OPTIONS,
OPT_PROV_OPTIONS,
{NULL}
};
#define IS_PROT_FLAG(o) \
(o == OPT_SSL3 || o == OPT_TLS1 || o == OPT_TLS1_1 || o == OPT_TLS1_2 \
|| o == OPT_TLS1_3 || o == OPT_DTLS || o == OPT_DTLS1 || o == OPT_DTLS1_2)
int s_server_main(int argc, char *argv[])
{
ENGINE *engine = NULL;
EVP_PKEY *s_key = NULL, *s_dkey = NULL;
SSL_CONF_CTX *cctx = NULL;
const SSL_METHOD *meth = TLS_server_method();
SSL_EXCERT *exc = NULL;
STACK_OF(OPENSSL_STRING) *ssl_args = NULL;
STACK_OF(X509) *s_chain = NULL, *s_dchain = NULL;
STACK_OF(X509_CRL) *crls = NULL;
X509 *s_cert = NULL, *s_dcert = NULL;
X509_VERIFY_PARAM *vpm = NULL;
const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL;
const char *chCApath = NULL, *chCAfile = NULL, *chCAstore = NULL;
char *dpassarg = NULL, *dpass = NULL;
char *passarg = NULL, *pass = NULL;
char *vfyCApath = NULL, *vfyCAfile = NULL, *vfyCAstore = NULL;
char *crl_file = NULL, *prog;
#ifdef AF_UNIX
int unlink_unix_path = 0;
#endif
do_server_cb server_cb;
int vpmtouched = 0, build_chain = 0, no_cache = 0, ext_cache = 0;
char *dhfile = NULL;
int no_dhe = 0;
int nocert = 0, ret = 1;
int noCApath = 0, noCAfile = 0, noCAstore = 0;
int s_cert_format = FORMAT_UNDEF, s_key_format = FORMAT_UNDEF;
int s_dcert_format = FORMAT_UNDEF, s_dkey_format = FORMAT_UNDEF;
int rev = 0, naccept = -1, sdebug = 0;
int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0;
int state = 0, crl_format = FORMAT_UNDEF, crl_download = 0;
char *host = NULL;
char *port = NULL;
unsigned char *context = NULL;
OPTION_CHOICE o;
EVP_PKEY *s_key2 = NULL;
X509 *s_cert2 = NULL;
tlsextctx tlsextcbp = { NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING };
const char *ssl_config = NULL;
int read_buf_len = 0;
#ifndef OPENSSL_NO_NEXTPROTONEG
const char *next_proto_neg_in = NULL;
tlsextnextprotoctx next_proto = { NULL, 0 };
#endif
const char *alpn_in = NULL;
tlsextalpnctx alpn_ctx = { NULL, 0 };
#ifndef OPENSSL_NO_PSK
/* by default do not send a PSK identity hint */
char *psk_identity_hint = NULL;
#endif
char *p;
#ifndef OPENSSL_NO_SRP
char *srpuserseed = NULL;
char *srp_verifier_file = NULL;
#endif
#ifndef OPENSSL_NO_SRTP
char *srtp_profiles = NULL;
#endif
int min_version = 0, max_version = 0, prot_opt = 0, no_prot_opt = 0;
int s_server_verify = SSL_VERIFY_NONE;
int s_server_session_id_context = 1; /* anything will do */
const char *s_cert_file = TEST_CERT, *s_key_file = NULL, *s_chain_file = NULL;
const char *s_cert_file2 = TEST_CERT2, *s_key_file2 = NULL;
char *s_dcert_file = NULL, *s_dkey_file = NULL, *s_dchain_file = NULL;
#ifndef OPENSSL_NO_OCSP
int s_tlsextstatus = 0;
#endif
int no_resume_ephemeral = 0;
unsigned int max_send_fragment = 0;
unsigned int split_send_fragment = 0, max_pipelines = 0;
const char *s_serverinfo_file = NULL;
const char *keylog_file = NULL;
int max_early_data = -1, recv_max_early_data = -1;
char *psksessf = NULL;
int no_ca_names = 0;
#ifndef OPENSSL_NO_SCTP
int sctp_label_bug = 0;
#endif
int ignore_unexpected_eof = 0;
/* Init of few remaining global variables */
local_argc = argc;
local_argv = argv;
ctx = ctx2 = NULL;
s_nbio = s_nbio_test = 0;
www = 0;
bio_s_out = NULL;
s_debug = 0;
s_msg = 0;
s_quiet = 0;
s_brief = 0;
async = 0;
use_sendfile = 0;
port = OPENSSL_strdup(PORT);
cctx = SSL_CONF_CTX_new();
vpm = X509_VERIFY_PARAM_new();
if (port == NULL || cctx == NULL || vpm == NULL)
goto end;
SSL_CONF_CTX_set_flags(cctx,
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CMDLINE);
prog = opt_init(argc, argv, s_server_options);
while ((o = opt_next()) != OPT_EOF) {
if (IS_PROT_FLAG(o) && ++prot_opt > 1) {
BIO_printf(bio_err, "Cannot supply multiple protocol flags\n");
goto end;
}
if (IS_NO_PROT_FLAG(o))
no_prot_opt++;
if (prot_opt == 1 && no_prot_opt) {
BIO_printf(bio_err,
"Cannot supply both a protocol flag and '-no_<prot>'\n");
goto end;
}
switch (o) {
case OPT_EOF:
case OPT_ERR:
opthelp:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
opt_help(s_server_options);
ret = 0;
goto end;
case OPT_4:
#ifdef AF_UNIX
if (socket_family == AF_UNIX) {
OPENSSL_free(host); host = NULL;
OPENSSL_free(port); port = NULL;
}
#endif
socket_family = AF_INET;
break;
case OPT_6:
if (1) {
#ifdef AF_INET6
#ifdef AF_UNIX
if (socket_family == AF_UNIX) {
OPENSSL_free(host); host = NULL;
OPENSSL_free(port); port = NULL;
}
#endif
socket_family = AF_INET6;
} else {
#endif
BIO_printf(bio_err, "%s: IPv6 domain sockets unsupported\n", prog);
goto end;
}
break;
case OPT_PORT:
#ifdef AF_UNIX
if (socket_family == AF_UNIX) {
socket_family = AF_UNSPEC;
}
#endif
OPENSSL_free(port); port = NULL;
OPENSSL_free(host); host = NULL;
if (BIO_parse_hostserv(opt_arg(), NULL, &port, BIO_PARSE_PRIO_SERV) < 1) {
BIO_printf(bio_err,
"%s: -port argument malformed or ambiguous\n",
port);
goto end;
}
break;
case OPT_ACCEPT:
#ifdef AF_UNIX
if (socket_family == AF_UNIX) {
socket_family = AF_UNSPEC;
}
#endif
OPENSSL_free(port); port = NULL;
OPENSSL_free(host); host = NULL;
if (BIO_parse_hostserv(opt_arg(), &host, &port, BIO_PARSE_PRIO_SERV) < 1) {
BIO_printf(bio_err,
"%s: -accept argument malformed or ambiguous\n",
port);
goto end;
}
break;
#ifdef AF_UNIX
case OPT_UNIX:
socket_family = AF_UNIX;
OPENSSL_free(host); host = OPENSSL_strdup(opt_arg());
if (host == NULL)
goto end;
OPENSSL_free(port); port = NULL;
break;
case OPT_UNLINK:
unlink_unix_path = 1;
break;
#endif
case OPT_NACCEPT:
naccept = atol(opt_arg());
break;
case OPT_VERIFY:
s_server_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
verify_args.depth = atoi(opt_arg());
if (!s_quiet)
BIO_printf(bio_err, "verify depth is %d\n", verify_args.depth);
break;
case OPT_UPPER_V_VERIFY:
s_server_verify =
SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
SSL_VERIFY_CLIENT_ONCE;
verify_args.depth = atoi(opt_arg());
if (!s_quiet)
BIO_printf(bio_err,
"verify depth is %d, must return a certificate\n",
verify_args.depth);
break;
case OPT_CONTEXT:
context = (unsigned char *)opt_arg();
break;
case OPT_CERT:
s_cert_file = opt_arg();
break;
case OPT_NAMEOPT:
if (!set_nameopt(opt_arg()))
goto end;
break;
case OPT_CRL:
crl_file = opt_arg();
break;
case OPT_CRL_DOWNLOAD:
crl_download = 1;
break;
case OPT_SERVERINFO:
s_serverinfo_file = opt_arg();
break;
case OPT_CERTFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_cert_format))
goto opthelp;
break;
case OPT_KEY:
s_key_file = opt_arg();
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_key_format))
goto opthelp;
break;
case OPT_PASS:
passarg = opt_arg();
break;
case OPT_CERT_CHAIN:
s_chain_file = opt_arg();
break;
case OPT_DHPARAM:
dhfile = opt_arg();
break;
case OPT_DCERTFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_dcert_format))
goto opthelp;
break;
case OPT_DCERT:
s_dcert_file = opt_arg();
break;
case OPT_DKEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_dkey_format))
goto opthelp;
break;
case OPT_DPASS:
dpassarg = opt_arg();
break;
case OPT_DKEY:
s_dkey_file = opt_arg();
break;
case OPT_DCERT_CHAIN:
s_dchain_file = opt_arg();
break;
case OPT_NOCERT:
nocert = 1;
break;
case OPT_CAPATH:
CApath = opt_arg();
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
case OPT_CHAINCAPATH:
chCApath = opt_arg();
break;
case OPT_VERIFYCAPATH:
vfyCApath = opt_arg();
break;
case OPT_CASTORE:
CAstore = opt_arg();
break;
case OPT_NOCASTORE:
noCAstore = 1;
break;
case OPT_CHAINCASTORE:
chCAstore = opt_arg();
break;
case OPT_VERIFYCASTORE:
vfyCAstore = opt_arg();
break;
case OPT_NO_CACHE:
no_cache = 1;
break;
case OPT_EXT_CACHE:
ext_cache = 1;
break;
case OPT_CRLFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &crl_format))
goto opthelp;
break;
case OPT_S_CASES:
case OPT_S_NUM_TICKETS:
case OPT_ANTI_REPLAY:
case OPT_NO_ANTI_REPLAY:
if (ssl_args == NULL)
ssl_args = sk_OPENSSL_STRING_new_null();
if (ssl_args == NULL
|| !sk_OPENSSL_STRING_push(ssl_args, opt_flag())
|| !sk_OPENSSL_STRING_push(ssl_args, opt_arg())) {
BIO_printf(bio_err, "%s: Memory allocation failure\n", prog);
goto end;
}
break;
case OPT_V_CASES:
if (!opt_verify(o, vpm))
goto end;
vpmtouched++;
break;
case OPT_X_CASES:
if (!args_excert(o, &exc))
goto end;
break;
case OPT_VERIFY_RET_ERROR:
verify_args.return_error = 1;
break;
case OPT_VERIFY_QUIET:
verify_args.quiet = 1;
break;
case OPT_BUILD_CHAIN:
build_chain = 1;
break;
case OPT_CAFILE:
CAfile = opt_arg();
break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_CHAINCAFILE:
chCAfile = opt_arg();
break;
case OPT_VERIFYCAFILE:
vfyCAfile = opt_arg();
break;
case OPT_NBIO:
s_nbio = 1;
break;
case OPT_NBIO_TEST:
s_nbio = s_nbio_test = 1;
break;
case OPT_IGN_EOF:
s_ign_eof = 1;
break;
case OPT_NO_IGN_EOF:
s_ign_eof = 0;
break;
case OPT_DEBUG:
s_debug = 1;
break;
case OPT_TLSEXTDEBUG:
s_tlsextdebug = 1;
break;
case OPT_STATUS:
#ifndef OPENSSL_NO_OCSP
s_tlsextstatus = 1;
#endif
break;
case OPT_STATUS_VERBOSE:
#ifndef OPENSSL_NO_OCSP
s_tlsextstatus = tlscstatp.verbose = 1;
#endif
break;
case OPT_STATUS_TIMEOUT:
#ifndef OPENSSL_NO_OCSP
s_tlsextstatus = 1;
tlscstatp.timeout = atoi(opt_arg());
#endif
break;
case OPT_PROXY:
#ifndef OPENSSL_NO_OCSP
tlscstatp.proxy = opt_arg();
#endif
break;
case OPT_NO_PROXY:
#ifndef OPENSSL_NO_OCSP
tlscstatp.no_proxy = opt_arg();
#endif
break;
case OPT_STATUS_URL:
#ifndef OPENSSL_NO_OCSP
s_tlsextstatus = 1;
if (!OSSL_HTTP_parse_url(opt_arg(), &tlscstatp.use_ssl, NULL,
&tlscstatp.host, &tlscstatp.port, NULL,
&tlscstatp.path, NULL, NULL)) {
BIO_printf(bio_err, "Error parsing -status_url argument\n");
goto end;
}
#endif
break;
case OPT_STATUS_FILE:
#ifndef OPENSSL_NO_OCSP
s_tlsextstatus = 1;
tlscstatp.respin = opt_arg();
#endif
break;
case OPT_MSG:
s_msg = 1;
break;
case OPT_MSGFILE:
bio_s_msg = BIO_new_file(opt_arg(), "w");
if (bio_s_msg == NULL) {
BIO_printf(bio_err, "Error writing file %s\n", opt_arg());
goto end;
}
break;
case OPT_TRACE:
#ifndef OPENSSL_NO_SSL_TRACE
s_msg = 2;
#endif
break;
case OPT_SECURITY_DEBUG:
sdebug = 1;
break;
case OPT_SECURITY_DEBUG_VERBOSE:
sdebug = 2;
break;
case OPT_STATE:
state = 1;
break;
case OPT_CRLF:
s_crlf = 1;
break;
case OPT_QUIET:
s_quiet = 1;
break;
case OPT_BRIEF:
s_quiet = s_brief = verify_args.quiet = 1;
break;
case OPT_NO_DHE:
no_dhe = 1;
break;
case OPT_NO_RESUME_EPHEMERAL:
no_resume_ephemeral = 1;
break;
case OPT_PSK_IDENTITY:
psk_identity = opt_arg();
break;
case OPT_PSK_HINT:
#ifndef OPENSSL_NO_PSK
psk_identity_hint = opt_arg();
#endif
break;
case OPT_PSK:
for (p = psk_key = opt_arg(); *p; p++) {
if (isxdigit(_UC(*p)))
continue;
BIO_printf(bio_err, "Not a hex number '%s'\n", psk_key);
goto end;
}
break;
case OPT_PSK_SESS:
psksessf = opt_arg();
break;
case OPT_SRPVFILE:
#ifndef OPENSSL_NO_SRP
srp_verifier_file = opt_arg();
if (min_version < TLS1_VERSION)
min_version = TLS1_VERSION;
#endif
break;
case OPT_SRPUSERSEED:
#ifndef OPENSSL_NO_SRP
srpuserseed = opt_arg();
if (min_version < TLS1_VERSION)
min_version = TLS1_VERSION;
#endif
break;
case OPT_REV:
rev = 1;
break;
case OPT_WWW:
www = 1;
break;
case OPT_UPPER_WWW:
www = 2;
break;
case OPT_HTTP:
www = 3;
break;
case OPT_SSL_CONFIG:
ssl_config = opt_arg();
break;
case OPT_SSL3:
min_version = SSL3_VERSION;
max_version = SSL3_VERSION;
break;
case OPT_TLS1_3:
min_version = TLS1_3_VERSION;
max_version = TLS1_3_VERSION;
break;
case OPT_TLS1_2:
min_version = TLS1_2_VERSION;
max_version = TLS1_2_VERSION;
break;
case OPT_TLS1_1:
min_version = TLS1_1_VERSION;
max_version = TLS1_1_VERSION;
break;
case OPT_TLS1:
min_version = TLS1_VERSION;
max_version = TLS1_VERSION;
break;
case OPT_DTLS:
#ifndef OPENSSL_NO_DTLS
meth = DTLS_server_method();
socket_type = SOCK_DGRAM;
#endif
break;
case OPT_DTLS1:
#ifndef OPENSSL_NO_DTLS
meth = DTLS_server_method();
min_version = DTLS1_VERSION;
max_version = DTLS1_VERSION;
socket_type = SOCK_DGRAM;
#endif
break;
case OPT_DTLS1_2:
#ifndef OPENSSL_NO_DTLS
meth = DTLS_server_method();
min_version = DTLS1_2_VERSION;
max_version = DTLS1_2_VERSION;
socket_type = SOCK_DGRAM;
#endif
break;
case OPT_SCTP:
#ifndef OPENSSL_NO_SCTP
protocol = IPPROTO_SCTP;
#endif
break;
case OPT_SCTP_LABEL_BUG:
#ifndef OPENSSL_NO_SCTP
sctp_label_bug = 1;
#endif
break;
case OPT_TIMEOUT:
#ifndef OPENSSL_NO_DTLS
enable_timeouts = 1;
#endif
break;
case OPT_MTU:
#ifndef OPENSSL_NO_DTLS
socket_mtu = atol(opt_arg());
#endif
break;
case OPT_LISTEN:
#ifndef OPENSSL_NO_DTLS
dtlslisten = 1;
#endif
break;
case OPT_STATELESS:
stateless = 1;
break;
case OPT_ID_PREFIX:
session_id_prefix = opt_arg();
break;
case OPT_ENGINE:
#ifndef OPENSSL_NO_ENGINE
engine = setup_engine(opt_arg(), s_debug);
#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_SERVERNAME:
tlsextcbp.servername = opt_arg();
break;
case OPT_SERVERNAME_FATAL:
tlsextcbp.extension_error = SSL_TLSEXT_ERR_ALERT_FATAL;
break;
case OPT_CERT2:
s_cert_file2 = opt_arg();
break;
case OPT_KEY2:
s_key_file2 = opt_arg();
break;
case OPT_NEXTPROTONEG:
# ifndef OPENSSL_NO_NEXTPROTONEG
next_proto_neg_in = opt_arg();
#endif
break;
case OPT_ALPN:
alpn_in = opt_arg();
break;
case OPT_SRTP_PROFILES:
#ifndef OPENSSL_NO_SRTP
srtp_profiles = opt_arg();
#endif
break;
case OPT_KEYMATEXPORT:
keymatexportlabel = opt_arg();
break;
case OPT_KEYMATEXPORTLEN:
keymatexportlen = atoi(opt_arg());
break;
case OPT_ASYNC:
async = 1;
break;
case OPT_MAX_SEND_FRAG:
max_send_fragment = atoi(opt_arg());
break;
case OPT_SPLIT_SEND_FRAG:
split_send_fragment = atoi(opt_arg());
break;
case OPT_MAX_PIPELINES:
max_pipelines = atoi(opt_arg());
break;
case OPT_READ_BUF:
read_buf_len = atoi(opt_arg());
break;
case OPT_KEYLOG_FILE:
keylog_file = opt_arg();
break;
case OPT_MAX_EARLY:
max_early_data = atoi(opt_arg());
if (max_early_data < 0) {
BIO_printf(bio_err, "Invalid value for max_early_data\n");
goto end;
}
break;
case OPT_RECV_MAX_EARLY:
recv_max_early_data = atoi(opt_arg());
if (recv_max_early_data < 0) {
BIO_printf(bio_err, "Invalid value for recv_max_early_data\n");
goto end;
}
break;
case OPT_EARLY_DATA:
early_data = 1;
if (max_early_data == -1)
max_early_data = SSL3_RT_MAX_PLAIN_LENGTH;
break;
case OPT_HTTP_SERVER_BINMODE:
http_server_binmode = 1;
break;
case OPT_NOCANAMES:
no_ca_names = 1;
break;
case OPT_SENDFILE:
#ifndef OPENSSL_NO_KTLS
use_sendfile = 1;
#endif
break;
case OPT_IGNORE_UNEXPECTED_EOF:
ignore_unexpected_eof = 1;
break;
}
}
/* No extra arguments. */
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
if (!app_RAND_load())
goto end;
#ifndef OPENSSL_NO_NEXTPROTONEG
if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) {
BIO_printf(bio_err, "Cannot supply -nextprotoneg with TLSv1.3\n");
goto opthelp;
}
#endif
#ifndef OPENSSL_NO_DTLS
if (www && socket_type == SOCK_DGRAM) {
BIO_printf(bio_err, "Can't use -HTTP, -www or -WWW with DTLS\n");
goto end;
}
if (dtlslisten && socket_type != SOCK_DGRAM) {
BIO_printf(bio_err, "Can only use -listen with DTLS\n");
goto end;
}
#endif
if (stateless && socket_type != SOCK_STREAM) {
BIO_printf(bio_err, "Can only use --stateless with TLS\n");
goto end;
}
#ifdef AF_UNIX
if (socket_family == AF_UNIX && socket_type != SOCK_STREAM) {
BIO_printf(bio_err,
"Can't use unix sockets and datagrams together\n");
goto end;
}
#endif
if (early_data && (www > 0 || rev)) {
BIO_printf(bio_err,
"Can't use -early_data in combination with -www, -WWW, -HTTP, or -rev\n");
goto end;
}
#ifndef OPENSSL_NO_SCTP
if (protocol == IPPROTO_SCTP) {
if (socket_type != SOCK_DGRAM) {
BIO_printf(bio_err, "Can't use -sctp without DTLS\n");
goto end;
}
/* SCTP is unusual. It uses DTLS over a SOCK_STREAM protocol */
socket_type = SOCK_STREAM;
}
#endif
#ifndef OPENSSL_NO_KTLS
if (use_sendfile && www <= 1) {
BIO_printf(bio_err, "Can't use -sendfile without -WWW or -HTTP\n");
goto end;
}
#endif
if (!app_passwd(passarg, dpassarg, &pass, &dpass)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
if (s_key_file == NULL)
s_key_file = s_cert_file;
if (s_key_file2 == NULL)
s_key_file2 = s_cert_file2;
if (!load_excert(&exc))
goto end;
if (nocert == 0) {
s_key = load_key(s_key_file, s_key_format, 0, pass, engine,
"server certificate private key");
if (s_key == NULL)
goto end;
s_cert = load_cert_pass(s_cert_file, s_cert_format, 1, pass,
"server certificate");
if (s_cert == NULL)
goto end;
if (s_chain_file != NULL) {
if (!load_certs(s_chain_file, 0, &s_chain, NULL,
"server certificate chain"))
goto end;
}
if (tlsextcbp.servername != NULL) {
s_key2 = load_key(s_key_file2, s_key_format, 0, pass, engine,
"second server certificate private key");
if (s_key2 == NULL)
goto end;
s_cert2 = load_cert_pass(s_cert_file2, s_cert_format, 1, pass,
"second server certificate");
if (s_cert2 == NULL)
goto end;
}
}
#if !defined(OPENSSL_NO_NEXTPROTONEG)
if (next_proto_neg_in) {
next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in);
if (next_proto.data == NULL)
goto end;
}
#endif
alpn_ctx.data = NULL;
if (alpn_in) {
alpn_ctx.data = next_protos_parse(&alpn_ctx.len, alpn_in);
if (alpn_ctx.data == NULL)
goto end;
}
if (crl_file != NULL) {
X509_CRL *crl;
crl = load_crl(crl_file, crl_format, 0, "CRL");
if (crl == NULL)
goto end;
crls = sk_X509_CRL_new_null();
if (crls == NULL || !sk_X509_CRL_push(crls, crl)) {
BIO_puts(bio_err, "Error adding CRL\n");
ERR_print_errors(bio_err);
X509_CRL_free(crl);
goto end;
}
}
if (s_dcert_file != NULL) {
if (s_dkey_file == NULL)
s_dkey_file = s_dcert_file;
s_dkey = load_key(s_dkey_file, s_dkey_format,
0, dpass, engine, "second certificate private key");
if (s_dkey == NULL)
goto end;
s_dcert = load_cert_pass(s_dcert_file, s_dcert_format, 1, dpass,
"second server certificate");
if (s_dcert == NULL) {
ERR_print_errors(bio_err);
goto end;
}
if (s_dchain_file != NULL) {
if (!load_certs(s_dchain_file, 0, &s_dchain, NULL,
"second server certificate chain"))
goto end;
}
}
if (bio_s_out == NULL) {
if (s_quiet && !s_debug) {
bio_s_out = BIO_new(BIO_s_null());
if (s_msg && bio_s_msg == NULL) {
bio_s_msg = dup_bio_out(FORMAT_TEXT);
if (bio_s_msg == NULL) {
BIO_printf(bio_err, "Out of memory\n");
goto end;
}
}
} else {
bio_s_out = dup_bio_out(FORMAT_TEXT);
}
}
if (bio_s_out == NULL)
goto end;
if (nocert) {
s_cert_file = NULL;
s_key_file = NULL;
s_dcert_file = NULL;
s_dkey_file = NULL;
s_cert_file2 = NULL;
s_key_file2 = NULL;
}
ctx = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth);
if (ctx == NULL) {
ERR_print_errors(bio_err);
goto end;
}
SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY);
if (sdebug)
ssl_ctx_security_debug(ctx, sdebug);
if (!config_ctx(cctx, ssl_args, ctx))
goto end;
if (ssl_config) {
if (SSL_CTX_config(ctx, ssl_config) == 0) {
BIO_printf(bio_err, "Error using configuration \"%s\"\n",
ssl_config);
ERR_print_errors(bio_err);
goto end;
}
}
#ifndef OPENSSL_NO_SCTP
if (protocol == IPPROTO_SCTP && sctp_label_bug == 1)
SSL_CTX_set_mode(ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG);
#endif
if (min_version != 0
&& SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
goto end;
if (max_version != 0
&& SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
goto end;
if (session_id_prefix) {
if (strlen(session_id_prefix) >= 32)
BIO_printf(bio_err,
"warning: id_prefix is too long, only one new session will be possible\n");
if (!SSL_CTX_set_generate_session_id(ctx, generate_session_id)) {
BIO_printf(bio_err, "error setting 'id_prefix'\n");
ERR_print_errors(bio_err);
goto end;
}
BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix);
}
if (exc != NULL)
ssl_ctx_set_excert(ctx, exc);
if (state)
SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
if (no_cache)
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
else if (ext_cache)
init_session_cache_ctx(ctx);
else
SSL_CTX_sess_set_cache_size(ctx, 128);
if (async) {
SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC);
}
if (no_ca_names) {
SSL_CTX_set_options(ctx, SSL_OP_DISABLE_TLSEXT_CA_NAMES);
}
if (ignore_unexpected_eof)
SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
if (max_send_fragment > 0
&& !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) {
BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n",
prog, max_send_fragment);
goto end;
}
if (split_send_fragment > 0
&& !SSL_CTX_set_split_send_fragment(ctx, split_send_fragment)) {
BIO_printf(bio_err, "%s: Split send fragment size %u is out of permitted range\n",
prog, split_send_fragment);
goto end;
}
if (max_pipelines > 0
&& !SSL_CTX_set_max_pipelines(ctx, max_pipelines)) {
BIO_printf(bio_err, "%s: Max pipelines %u is out of permitted range\n",
prog, max_pipelines);
goto end;
}
if (read_buf_len > 0) {
SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len);
}
#ifndef OPENSSL_NO_SRTP
if (srtp_profiles != NULL) {
/* Returns 0 on success! */
if (SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles) != 0) {
BIO_printf(bio_err, "Error setting SRTP profile\n");
ERR_print_errors(bio_err);
goto end;
}
}
#endif
if (!ctx_set_verify_locations(ctx, CAfile, noCAfile, CApath, noCApath,
CAstore, noCAstore)) {
ERR_print_errors(bio_err);
goto end;
}
if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) {
BIO_printf(bio_err, "Error setting verify params\n");
ERR_print_errors(bio_err);
goto end;
}
ssl_ctx_add_crls(ctx, crls, 0);
if (!ssl_load_stores(ctx,
vfyCApath, vfyCAfile, vfyCAstore,
chCApath, chCAfile, chCAstore,
crls, crl_download)) {
BIO_printf(bio_err, "Error loading store locations\n");
ERR_print_errors(bio_err);
goto end;
}
if (s_cert2) {
ctx2 = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth);
if (ctx2 == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
if (ctx2 != NULL) {
BIO_printf(bio_s_out, "Setting secondary ctx parameters\n");
if (sdebug)
ssl_ctx_security_debug(ctx2, sdebug);
if (session_id_prefix) {
if (strlen(session_id_prefix) >= 32)
BIO_printf(bio_err,
"warning: id_prefix is too long, only one new session will be possible\n");
if (!SSL_CTX_set_generate_session_id(ctx2, generate_session_id)) {
BIO_printf(bio_err, "error setting 'id_prefix'\n");
ERR_print_errors(bio_err);
goto end;
}
BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix);
}
if (exc != NULL)
ssl_ctx_set_excert(ctx2, exc);
if (state)
SSL_CTX_set_info_callback(ctx2, apps_ssl_info_callback);
if (no_cache)
SSL_CTX_set_session_cache_mode(ctx2, SSL_SESS_CACHE_OFF);
else if (ext_cache)
init_session_cache_ctx(ctx2);
else
SSL_CTX_sess_set_cache_size(ctx2, 128);
if (async)
SSL_CTX_set_mode(ctx2, SSL_MODE_ASYNC);
if (!ctx_set_verify_locations(ctx2, CAfile, noCAfile, CApath,
noCApath, CAstore, noCAstore)) {
ERR_print_errors(bio_err);
goto end;
}
if (vpmtouched && !SSL_CTX_set1_param(ctx2, vpm)) {
BIO_printf(bio_err, "Error setting verify params\n");
ERR_print_errors(bio_err);
goto end;
}
ssl_ctx_add_crls(ctx2, crls, 0);
if (!config_ctx(cctx, ssl_args, ctx2))
goto end;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
if (next_proto.data)
SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb,
&next_proto);
#endif
if (alpn_ctx.data)
SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx);
if (!no_dhe) {
EVP_PKEY *dhpkey = NULL;
if (dhfile != NULL)
dhpkey = load_keyparams(dhfile, FORMAT_UNDEF, 0, "DH", "DH parameters");
else if (s_cert_file != NULL)
dhpkey = load_keyparams_suppress(s_cert_file, FORMAT_UNDEF, 0, "DH",
"DH parameters", 1);
if (dhpkey != NULL) {
BIO_printf(bio_s_out, "Setting temp DH parameters\n");
} else {
BIO_printf(bio_s_out, "Using default temp DH parameters\n");
}
(void)BIO_flush(bio_s_out);
if (dhpkey == NULL) {
SSL_CTX_set_dh_auto(ctx, 1);
} else {
/*
* We need 2 references: one for use by ctx and one for use by
* ctx2
*/
if (!EVP_PKEY_up_ref(dhpkey)) {
EVP_PKEY_free(dhpkey);
goto end;
}
if (!SSL_CTX_set0_tmp_dh_pkey(ctx, dhpkey)) {
BIO_puts(bio_err, "Error setting temp DH parameters\n");
ERR_print_errors(bio_err);
/* Free 2 references */
EVP_PKEY_free(dhpkey);
EVP_PKEY_free(dhpkey);
goto end;
}
}
if (ctx2 != NULL) {
if (dhfile != NULL) {
EVP_PKEY *dhpkey2 = load_keyparams_suppress(s_cert_file2,
FORMAT_UNDEF,
0, "DH",
"DH parameters", 1);
if (dhpkey2 != NULL) {
BIO_printf(bio_s_out, "Setting temp DH parameters\n");
(void)BIO_flush(bio_s_out);
EVP_PKEY_free(dhpkey);
dhpkey = dhpkey2;
}
}
if (dhpkey == NULL) {
SSL_CTX_set_dh_auto(ctx2, 1);
} else if (!SSL_CTX_set0_tmp_dh_pkey(ctx2, dhpkey)) {
BIO_puts(bio_err, "Error setting temp DH parameters\n");
ERR_print_errors(bio_err);
EVP_PKEY_free(dhpkey);
goto end;
}
dhpkey = NULL;
}
EVP_PKEY_free(dhpkey);
}
if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain))
goto end;
if (s_serverinfo_file != NULL
&& !SSL_CTX_use_serverinfo_file(ctx, s_serverinfo_file)) {
ERR_print_errors(bio_err);
goto end;
}
if (ctx2 != NULL
&& !set_cert_key_stuff(ctx2, s_cert2, s_key2, NULL, build_chain))
goto end;
if (s_dcert != NULL) {
if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, s_dchain, build_chain))
goto end;
}
if (no_resume_ephemeral) {
SSL_CTX_set_not_resumable_session_callback(ctx,
not_resumable_sess_cb);
if (ctx2 != NULL)
SSL_CTX_set_not_resumable_session_callback(ctx2,
not_resumable_sess_cb);
}
#ifndef OPENSSL_NO_PSK
if (psk_key != NULL) {
if (s_debug)
BIO_printf(bio_s_out, "PSK key given, setting server callback\n");
SSL_CTX_set_psk_server_callback(ctx, psk_server_cb);
}
if (psk_identity_hint != NULL) {
if (min_version == TLS1_3_VERSION) {
BIO_printf(bio_s_out, "PSK warning: there is NO identity hint in TLSv1.3\n");
} else {
if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) {
BIO_printf(bio_err, "error setting PSK identity hint to context\n");
ERR_print_errors(bio_err);
goto end;
}
}
}
#endif
if (psksessf != NULL) {
BIO *stmp = BIO_new_file(psksessf, "r");
if (stmp == NULL) {
BIO_printf(bio_err, "Can't open PSK session file %s\n", psksessf);
ERR_print_errors(bio_err);
goto end;
}
psksess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
BIO_free(stmp);
if (psksess == NULL) {
BIO_printf(bio_err, "Can't read PSK session file %s\n", psksessf);
ERR_print_errors(bio_err);
goto end;
}
}
if (psk_key != NULL || psksess != NULL)
SSL_CTX_set_psk_find_session_callback(ctx, psk_find_session_cb);
SSL_CTX_set_verify(ctx, s_server_verify, verify_callback);
if (!SSL_CTX_set_session_id_context(ctx,
(void *)&s_server_session_id_context,
sizeof(s_server_session_id_context))) {
BIO_printf(bio_err, "error setting session id context\n");
ERR_print_errors(bio_err);
goto end;
}
/* Set DTLS cookie generation and verification callbacks */
SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback);
SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback);
/* Set TLS1.3 cookie generation and verification callbacks */
SSL_CTX_set_stateless_cookie_generate_cb(ctx, generate_stateless_cookie_callback);
SSL_CTX_set_stateless_cookie_verify_cb(ctx, verify_stateless_cookie_callback);
if (ctx2 != NULL) {
SSL_CTX_set_verify(ctx2, s_server_verify, verify_callback);
if (!SSL_CTX_set_session_id_context(ctx2,
(void *)&s_server_session_id_context,
sizeof(s_server_session_id_context))) {
BIO_printf(bio_err, "error setting session id context\n");
ERR_print_errors(bio_err);
goto end;
}
tlsextcbp.biodebug = bio_s_out;
SSL_CTX_set_tlsext_servername_callback(ctx2, ssl_servername_cb);
SSL_CTX_set_tlsext_servername_arg(ctx2, &tlsextcbp);
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
}
#ifndef OPENSSL_NO_SRP
if (srp_verifier_file != NULL) {
if (!set_up_srp_verifier_file(ctx, &srp_callback_parm, srpuserseed,
srp_verifier_file))
goto end;
} else
#endif
if (CAfile != NULL) {
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAfile));
if (ctx2)
SSL_CTX_set_client_CA_list(ctx2, SSL_load_client_CA_file(CAfile));
}
#ifndef OPENSSL_NO_OCSP
if (s_tlsextstatus) {
SSL_CTX_set_tlsext_status_cb(ctx, cert_status_cb);
SSL_CTX_set_tlsext_status_arg(ctx, &tlscstatp);
if (ctx2) {
SSL_CTX_set_tlsext_status_cb(ctx2, cert_status_cb);
SSL_CTX_set_tlsext_status_arg(ctx2, &tlscstatp);
}
}
#endif
if (set_keylog_file(ctx, keylog_file))
goto end;
if (max_early_data >= 0)
SSL_CTX_set_max_early_data(ctx, max_early_data);
if (recv_max_early_data >= 0)
SSL_CTX_set_recv_max_early_data(ctx, recv_max_early_data);
if (rev)
server_cb = rev_body;
else if (www)
server_cb = www_body;
else
server_cb = sv_body;
#ifdef AF_UNIX
if (socket_family == AF_UNIX
&& unlink_unix_path)
unlink(host);
#endif
do_server(&accept_socket, host, port, socket_family, socket_type, protocol,
server_cb, context, naccept, bio_s_out);
print_stats(bio_s_out, ctx);
ret = 0;
end:
SSL_CTX_free(ctx);
SSL_SESSION_free(psksess);
set_keylog_file(NULL, NULL);
X509_free(s_cert);
sk_X509_CRL_pop_free(crls, X509_CRL_free);
X509_free(s_dcert);
EVP_PKEY_free(s_key);
EVP_PKEY_free(s_dkey);
sk_X509_pop_free(s_chain, X509_free);
sk_X509_pop_free(s_dchain, X509_free);
OPENSSL_free(pass);
OPENSSL_free(dpass);
OPENSSL_free(host);
OPENSSL_free(port);
X509_VERIFY_PARAM_free(vpm);
free_sessions();
OPENSSL_free(tlscstatp.host);
OPENSSL_free(tlscstatp.port);
OPENSSL_free(tlscstatp.path);
SSL_CTX_free(ctx2);
X509_free(s_cert2);
EVP_PKEY_free(s_key2);
#ifndef OPENSSL_NO_NEXTPROTONEG
OPENSSL_free(next_proto.data);
#endif
OPENSSL_free(alpn_ctx.data);
ssl_excert_free(exc);
sk_OPENSSL_STRING_free(ssl_args);
SSL_CONF_CTX_free(cctx);
release_engine(engine);
BIO_free(bio_s_out);
bio_s_out = NULL;
BIO_free(bio_s_msg);
bio_s_msg = NULL;
#ifdef CHARSET_EBCDIC
BIO_meth_free(methods_ebcdic);
#endif
return ret;
}
static void print_stats(BIO *bio, SSL_CTX *ssl_ctx)
{
BIO_printf(bio, "%4ld items in the session cache\n",
SSL_CTX_sess_number(ssl_ctx));
BIO_printf(bio, "%4ld client connects (SSL_connect())\n",
SSL_CTX_sess_connect(ssl_ctx));
BIO_printf(bio, "%4ld client renegotiates (SSL_connect())\n",
SSL_CTX_sess_connect_renegotiate(ssl_ctx));
BIO_printf(bio, "%4ld client connects that finished\n",
SSL_CTX_sess_connect_good(ssl_ctx));
BIO_printf(bio, "%4ld server accepts (SSL_accept())\n",
SSL_CTX_sess_accept(ssl_ctx));
BIO_printf(bio, "%4ld server renegotiates (SSL_accept())\n",
SSL_CTX_sess_accept_renegotiate(ssl_ctx));
BIO_printf(bio, "%4ld server accepts that finished\n",
SSL_CTX_sess_accept_good(ssl_ctx));
BIO_printf(bio, "%4ld session cache hits\n", SSL_CTX_sess_hits(ssl_ctx));
BIO_printf(bio, "%4ld session cache misses\n",
SSL_CTX_sess_misses(ssl_ctx));
BIO_printf(bio, "%4ld session cache timeouts\n",
SSL_CTX_sess_timeouts(ssl_ctx));
BIO_printf(bio, "%4ld callback cache hits\n",
SSL_CTX_sess_cb_hits(ssl_ctx));
BIO_printf(bio, "%4ld cache full overflows (%ld allowed)\n",
SSL_CTX_sess_cache_full(ssl_ctx),
SSL_CTX_sess_get_cache_size(ssl_ctx));
}
static long int count_reads_callback(BIO *bio, int cmd, const char *argp, size_t len,
int argi, long argl, int ret, size_t *processed)
{
unsigned int *p_counter = (unsigned int *)BIO_get_callback_arg(bio);
switch (cmd) {
case BIO_CB_READ: /* No break here */
case BIO_CB_GETS:
if (p_counter != NULL)
++*p_counter;
break;
default:
break;
}
if (s_debug) {
BIO_set_callback_arg(bio, (char *)bio_s_out);
ret = (int)bio_dump_callback(bio, cmd, argp, len, argi, argl, ret, processed);
BIO_set_callback_arg(bio, (char *)p_counter);
}
return ret;
}
static int sv_body(int s, int stype, int prot, unsigned char *context)
{
char *buf = NULL;
fd_set readfds;
int ret = 1, width;
int k, i;
unsigned long l;
SSL *con = NULL;
BIO *sbio;
struct timeval timeout;
#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS))
struct timeval *timeoutp;
#endif
#ifndef OPENSSL_NO_DTLS
# ifndef OPENSSL_NO_SCTP
int isdtls = (stype == SOCK_DGRAM || prot == IPPROTO_SCTP);
# else
int isdtls = (stype == SOCK_DGRAM);
# endif
#endif
buf = app_malloc(bufsize, "server buffer");
if (s_nbio) {
if (!BIO_socket_nbio(s, 1))
ERR_print_errors(bio_err);
else if (!s_quiet)
BIO_printf(bio_err, "Turned on non blocking io\n");
}
con = SSL_new(ctx);
if (con == NULL) {
ret = -1;
goto err;
}
if (s_tlsextdebug) {
SSL_set_tlsext_debug_callback(con, tlsext_cb);
SSL_set_tlsext_debug_arg(con, bio_s_out);
}
if (context != NULL
&& !SSL_set_session_id_context(con, context,
strlen((char *)context))) {
BIO_printf(bio_err, "Error setting session id context\n");
ret = -1;
goto err;
}
if (!SSL_clear(con)) {
BIO_printf(bio_err, "Error clearing SSL connection\n");
ret = -1;
goto err;
}
#ifndef OPENSSL_NO_DTLS
if (isdtls) {
# ifndef OPENSSL_NO_SCTP
if (prot == IPPROTO_SCTP)
sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE);
else
# endif
sbio = BIO_new_dgram(s, BIO_NOCLOSE);
if (sbio == NULL) {
BIO_printf(bio_err, "Unable to create BIO\n");
ERR_print_errors(bio_err);
goto err;
}
if (enable_timeouts) {
timeout.tv_sec = 0;
timeout.tv_usec = DGRAM_RCV_TIMEOUT;
BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
timeout.tv_sec = 0;
timeout.tv_usec = DGRAM_SND_TIMEOUT;
BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
}
if (socket_mtu) {
if (socket_mtu < DTLS_get_link_min_mtu(con)) {
BIO_printf(bio_err, "MTU too small. Must be at least %ld\n",
DTLS_get_link_min_mtu(con));
ret = -1;
BIO_free(sbio);
goto err;
}
SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
if (!DTLS_set_link_mtu(con, socket_mtu)) {
BIO_printf(bio_err, "Failed to set MTU\n");
ret = -1;
BIO_free(sbio);
goto err;
}
} else
/* want to do MTU discovery */
BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
# ifndef OPENSSL_NO_SCTP
if (prot != IPPROTO_SCTP)
# endif
/* Turn on cookie exchange. Not necessary for SCTP */
SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE);
} else
#endif
sbio = BIO_new_socket(s, BIO_NOCLOSE);
if (sbio == NULL) {
BIO_printf(bio_err, "Unable to create BIO\n");
ERR_print_errors(bio_err);
goto err;
}
if (s_nbio_test) {
BIO *test;
test = BIO_new(BIO_f_nbio_test());
if (test == NULL) {
BIO_printf(bio_err, "Unable to create BIO\n");
ret = -1;
BIO_free(sbio);
goto err;
}
sbio = BIO_push(test, sbio);
}
SSL_set_bio(con, sbio, sbio);
SSL_set_accept_state(con);
/* SSL_set_fd(con,s); */
BIO_set_callback_ex(SSL_get_rbio(con), count_reads_callback);
if (s_msg) {
#ifndef OPENSSL_NO_SSL_TRACE
if (s_msg == 2)
SSL_set_msg_callback(con, SSL_trace);
else
#endif
SSL_set_msg_callback(con, msg_cb);
SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out);
}
if (s_tlsextdebug) {
SSL_set_tlsext_debug_callback(con, tlsext_cb);
SSL_set_tlsext_debug_arg(con, bio_s_out);
}
if (early_data) {
int write_header = 1, edret = SSL_READ_EARLY_DATA_ERROR;
size_t readbytes;
while (edret != SSL_READ_EARLY_DATA_FINISH) {
for (;;) {
edret = SSL_read_early_data(con, buf, bufsize, &readbytes);
if (edret != SSL_READ_EARLY_DATA_ERROR)
break;
switch (SSL_get_error(con, 0)) {
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_ASYNC:
case SSL_ERROR_WANT_READ:
/* Just keep trying - busy waiting */
continue;
default:
BIO_printf(bio_err, "Error reading early data\n");
ERR_print_errors(bio_err);
goto err;
}
}
if (readbytes > 0) {
if (write_header) {
BIO_printf(bio_s_out, "Early data received:\n");
write_header = 0;
}
raw_write_stdout(buf, (unsigned int)readbytes);
(void)BIO_flush(bio_s_out);
}
}
if (write_header) {
if (SSL_get_early_data_status(con) == SSL_EARLY_DATA_NOT_SENT)
BIO_printf(bio_s_out, "No early data received\n");
else
BIO_printf(bio_s_out, "Early data was rejected\n");
} else {
BIO_printf(bio_s_out, "\nEnd of early data\n");
}
if (SSL_is_init_finished(con))
print_connection_info(con);
}
if (fileno_stdin() > s)
width = fileno_stdin() + 1;
else
width = s + 1;
for (;;) {
int read_from_terminal;
int read_from_sslcon;
read_from_terminal = 0;
read_from_sslcon = SSL_has_pending(con)
|| (async && SSL_waiting_for_async(con));
if (!read_from_sslcon) {
FD_ZERO(&readfds);
#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS)
openssl_fdset(fileno_stdin(), &readfds);
#endif
openssl_fdset(s, &readfds);
/*
* Note: under VMS with SOCKETSHR the second parameter is
* currently of type (int *) whereas under other systems it is
* (void *) if you don't have a cast it will choke the compiler:
* if you do have a cast then you can either go for (int *) or
* (void *).
*/
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
/*
* Under DOS (non-djgpp) and Windows we can't select on stdin:
* only on sockets. As a workaround we timeout the select every
* second and check for any keypress. In a proper Windows
* application we wouldn't do this because it is inefficient.
*/
timeout.tv_sec = 1;
timeout.tv_usec = 0;
i = select(width, (void *)&readfds, NULL, NULL, &timeout);
if (has_stdin_waiting())
read_from_terminal = 1;
if ((i < 0) || (!i && !read_from_terminal))
continue;
#else
if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout))
timeoutp = &timeout;
else
timeoutp = NULL;
i = select(width, (void *)&readfds, NULL, NULL, timeoutp);
if ((SSL_is_dtls(con)) && DTLSv1_handle_timeout(con) > 0)
BIO_printf(bio_err, "TIMEOUT occurred\n");
if (i <= 0)
continue;
if (FD_ISSET(fileno_stdin(), &readfds))
read_from_terminal = 1;
#endif
if (FD_ISSET(s, &readfds))
read_from_sslcon = 1;
}
if (read_from_terminal) {
if (s_crlf) {
int j, lf_num;
i = raw_read_stdin(buf, bufsize / 2);
lf_num = 0;
/* both loops are skipped when i <= 0 */
for (j = 0; j < i; j++)
if (buf[j] == '\n')
lf_num++;
for (j = i - 1; j >= 0; j--) {
buf[j + lf_num] = buf[j];
if (buf[j] == '\n') {
lf_num--;
i++;
buf[j + lf_num] = '\r';
}
}
assert(lf_num == 0);
} else {
i = raw_read_stdin(buf, bufsize);
}
if (!s_quiet && !s_brief) {
if ((i <= 0) || (buf[0] == 'Q')) {
BIO_printf(bio_s_out, "DONE\n");
(void)BIO_flush(bio_s_out);
BIO_closesocket(s);
close_accept_socket();
ret = -11;
goto err;
}
if ((i <= 0) || (buf[0] == 'q')) {
BIO_printf(bio_s_out, "DONE\n");
(void)BIO_flush(bio_s_out);
if (SSL_version(con) != DTLS1_VERSION)
BIO_closesocket(s);
/*
* close_accept_socket(); ret= -11;
*/
goto err;
}
if ((buf[0] == 'r') && ((buf[1] == '\n') || (buf[1] == '\r'))) {
SSL_renegotiate(con);
i = SSL_do_handshake(con);
printf("SSL_do_handshake -> %d\n", i);
i = 0; /* 13; */
continue;
}
if ((buf[0] == 'R') && ((buf[1] == '\n') || (buf[1] == '\r'))) {
SSL_set_verify(con,
SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
NULL);
SSL_renegotiate(con);
i = SSL_do_handshake(con);
printf("SSL_do_handshake -> %d\n", i);
i = 0; /* 13; */
continue;
}
if ((buf[0] == 'K' || buf[0] == 'k')
&& ((buf[1] == '\n') || (buf[1] == '\r'))) {
SSL_key_update(con, buf[0] == 'K' ?
SSL_KEY_UPDATE_REQUESTED
: SSL_KEY_UPDATE_NOT_REQUESTED);
i = SSL_do_handshake(con);
printf("SSL_do_handshake -> %d\n", i);
i = 0;
continue;
}
if (buf[0] == 'c' && ((buf[1] == '\n') || (buf[1] == '\r'))) {
SSL_set_verify(con, SSL_VERIFY_PEER, NULL);
i = SSL_verify_client_post_handshake(con);
if (i == 0) {
printf("Failed to initiate request\n");
ERR_print_errors(bio_err);
} else {
i = SSL_do_handshake(con);
printf("SSL_do_handshake -> %d\n", i);
i = 0;
}
continue;
}
if (buf[0] == 'P') {
static const char str[] = "Lets print some clear text\n";
BIO_write(SSL_get_wbio(con), str, sizeof(str) -1);
}
if (buf[0] == 'S') {
print_stats(bio_s_out, SSL_get_SSL_CTX(con));
}
}
#ifdef CHARSET_EBCDIC
ebcdic2ascii(buf, buf, i);
#endif
l = k = 0;
for (;;) {
/* should do a select for the write */
#ifdef RENEG
static count = 0;
if (++count == 100) {
count = 0;
SSL_renegotiate(con);
}
#endif
k = SSL_write(con, &(buf[l]), (unsigned int)i);
#ifndef OPENSSL_NO_SRP
while (SSL_get_error(con, k) == SSL_ERROR_WANT_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during write\n");
lookup_srp_user(&srp_callback_parm, bio_s_out);
k = SSL_write(con, &(buf[l]), (unsigned int)i);
}
#endif
switch (SSL_get_error(con, k)) {
case SSL_ERROR_NONE:
break;
case SSL_ERROR_WANT_ASYNC:
BIO_printf(bio_s_out, "Write BLOCK (Async)\n");
(void)BIO_flush(bio_s_out);
wait_for_async(con);
break;
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_X509_LOOKUP:
BIO_printf(bio_s_out, "Write BLOCK\n");
(void)BIO_flush(bio_s_out);
break;
case SSL_ERROR_WANT_ASYNC_JOB:
/*
* This shouldn't ever happen in s_server. Treat as an error
*/
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
BIO_printf(bio_s_out, "ERROR\n");
(void)BIO_flush(bio_s_out);
ERR_print_errors(bio_err);
ret = 1;
goto err;
/* break; */
case SSL_ERROR_ZERO_RETURN:
BIO_printf(bio_s_out, "DONE\n");
(void)BIO_flush(bio_s_out);
ret = 1;
goto err;
}
if (k > 0) {
l += k;
i -= k;
}
if (i <= 0)
break;
}
}
if (read_from_sslcon) {
/*
* init_ssl_connection handles all async events itself so if we're
* waiting for async then we shouldn't go back into
* init_ssl_connection
*/
if ((!async || !SSL_waiting_for_async(con))
&& !SSL_is_init_finished(con)) {
/*
* Count number of reads during init_ssl_connection.
* It helps us to distinguish configuration errors from errors
* caused by a client.
*/
unsigned int read_counter = 0;
BIO_set_callback_arg(SSL_get_rbio(con), (char *)&read_counter);
i = init_ssl_connection(con);
BIO_set_callback_arg(SSL_get_rbio(con), NULL);
/*
* If initialization fails without reads, then
* there was a fatal error in configuration.
*/
if (i <= 0 && read_counter == 0) {
ret = -1;
goto err;
}
if (i < 0) {
ret = 0;
goto err;
} else if (i == 0) {
ret = 1;
goto err;
}
} else {
again:
i = SSL_read(con, (char *)buf, bufsize);
#ifndef OPENSSL_NO_SRP
while (SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during read\n");
lookup_srp_user(&srp_callback_parm, bio_s_out);
i = SSL_read(con, (char *)buf, bufsize);
}
#endif
switch (SSL_get_error(con, i)) {
case SSL_ERROR_NONE:
#ifdef CHARSET_EBCDIC
ascii2ebcdic(buf, buf, i);
#endif
raw_write_stdout(buf, (unsigned int)i);
(void)BIO_flush(bio_s_out);
if (SSL_has_pending(con))
goto again;
break;
case SSL_ERROR_WANT_ASYNC:
BIO_printf(bio_s_out, "Read BLOCK (Async)\n");
(void)BIO_flush(bio_s_out);
wait_for_async(con);
break;
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_READ:
BIO_printf(bio_s_out, "Read BLOCK\n");
(void)BIO_flush(bio_s_out);
break;
case SSL_ERROR_WANT_ASYNC_JOB:
/*
* This shouldn't ever happen in s_server. Treat as an error
*/
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
BIO_printf(bio_s_out, "ERROR\n");
(void)BIO_flush(bio_s_out);
ERR_print_errors(bio_err);
ret = 1;
goto err;
case SSL_ERROR_ZERO_RETURN:
BIO_printf(bio_s_out, "DONE\n");
(void)BIO_flush(bio_s_out);
ret = 1;
goto err;
}
}
}
}
err:
if (con != NULL) {
BIO_printf(bio_s_out, "shutting down SSL\n");
do_ssl_shutdown(con);
SSL_free(con);
}
BIO_printf(bio_s_out, "CONNECTION CLOSED\n");
OPENSSL_clear_free(buf, bufsize);
return ret;
}
static void close_accept_socket(void)
{
BIO_printf(bio_err, "shutdown accept socket\n");
if (accept_socket >= 0) {
BIO_closesocket(accept_socket);
}
}
static int is_retryable(SSL *con, int i)
{
int err = SSL_get_error(con, i);
/* If it's not a fatal error, it must be retryable */
return (err != SSL_ERROR_SSL)
&& (err != SSL_ERROR_SYSCALL)
&& (err != SSL_ERROR_ZERO_RETURN);
}
static int init_ssl_connection(SSL *con)
{
int i;
long verify_err;
int retry = 0;
if (dtlslisten || stateless) {
BIO_ADDR *client = NULL;
if (dtlslisten) {
if ((client = BIO_ADDR_new()) == NULL) {
BIO_printf(bio_err, "ERROR - memory\n");
return 0;
}
i = DTLSv1_listen(con, client);
} else {
i = SSL_stateless(con);
}
if (i > 0) {
BIO *wbio;
int fd = -1;
if (dtlslisten) {
wbio = SSL_get_wbio(con);
if (wbio) {
BIO_get_fd(wbio, &fd);
}
if (!wbio || BIO_connect(fd, client, 0) == 0) {
BIO_printf(bio_err, "ERROR - unable to connect\n");
BIO_ADDR_free(client);
return 0;
}
(void)BIO_ctrl_set_connected(wbio, client);
BIO_ADDR_free(client);
dtlslisten = 0;
} else {
stateless = 0;
}
i = SSL_accept(con);
} else {
BIO_ADDR_free(client);
}
} else {
do {
i = SSL_accept(con);
if (i <= 0)
retry = is_retryable(con, i);
#ifdef CERT_CB_TEST_RETRY
{
while (i <= 0
&& SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP
&& SSL_get_state(con) == TLS_ST_SR_CLNT_HELLO) {
BIO_printf(bio_err,
"LOOKUP from certificate callback during accept\n");
i = SSL_accept(con);
if (i <= 0)
retry = is_retryable(con, i);
}
}
#endif
#ifndef OPENSSL_NO_SRP
while (i <= 0
&& SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP during accept %s\n",
srp_callback_parm.login);
lookup_srp_user(&srp_callback_parm, bio_s_out);
i = SSL_accept(con);
if (i <= 0)
retry = is_retryable(con, i);
}
#endif
} while (i < 0 && SSL_waiting_for_async(con));
}
if (i <= 0) {
if (((dtlslisten || stateless) && i == 0)
|| (!dtlslisten && !stateless && retry)) {
BIO_printf(bio_s_out, "DELAY\n");
return 1;
}
BIO_printf(bio_err, "ERROR\n");
verify_err = SSL_get_verify_result(con);
if (verify_err != X509_V_OK) {
BIO_printf(bio_err, "verify error:%s\n",
X509_verify_cert_error_string(verify_err));
}
/* Always print any error messages */
ERR_print_errors(bio_err);
return 0;
}
print_connection_info(con);
return 1;
}
static void print_connection_info(SSL *con)
{
const char *str;
X509 *peer;
char buf[BUFSIZ];
#if !defined(OPENSSL_NO_NEXTPROTONEG)
const unsigned char *next_proto_neg;
unsigned next_proto_neg_len;
#endif
unsigned char *exportedkeymat;
int i;
if (s_brief)
print_ssl_summary(con);
PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con));
peer = SSL_get0_peer_certificate(con);
if (peer != NULL) {
BIO_printf(bio_s_out, "Client certificate\n");
PEM_write_bio_X509(bio_s_out, peer);
dump_cert_text(bio_s_out, peer);
peer = NULL;
}
if (SSL_get_shared_ciphers(con, buf, sizeof(buf)) != NULL)
BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf);
str = SSL_CIPHER_get_name(SSL_get_current_cipher(con));
ssl_print_sigalgs(bio_s_out, con);
#ifndef OPENSSL_NO_EC
ssl_print_point_formats(bio_s_out, con);
ssl_print_groups(bio_s_out, con, 0);
#endif
print_ca_names(bio_s_out, con);
BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)");
#if !defined(OPENSSL_NO_NEXTPROTONEG)
SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len);
if (next_proto_neg) {
BIO_printf(bio_s_out, "NEXTPROTO is ");
BIO_write(bio_s_out, next_proto_neg, next_proto_neg_len);
BIO_printf(bio_s_out, "\n");
}
#endif
#ifndef OPENSSL_NO_SRTP
{
SRTP_PROTECTION_PROFILE *srtp_profile
= SSL_get_selected_srtp_profile(con);
if (srtp_profile)
BIO_printf(bio_s_out, "SRTP Extension negotiated, profile=%s\n",
srtp_profile->name);
}
#endif
if (SSL_session_reused(con))
BIO_printf(bio_s_out, "Reused session-id\n");
BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n",
SSL_get_secure_renegotiation_support(con) ? "" : " NOT");
if ((SSL_get_options(con) & SSL_OP_NO_RENEGOTIATION))
BIO_printf(bio_s_out, "Renegotiation is DISABLED\n");
if (keymatexportlabel != NULL) {
BIO_printf(bio_s_out, "Keying material exporter:\n");
BIO_printf(bio_s_out, " Label: '%s'\n", keymatexportlabel);
BIO_printf(bio_s_out, " Length: %i bytes\n", keymatexportlen);
exportedkeymat = app_malloc(keymatexportlen, "export key");
if (SSL_export_keying_material(con, exportedkeymat,
keymatexportlen,
keymatexportlabel,
strlen(keymatexportlabel),
NULL, 0, 0) <= 0) {
BIO_printf(bio_s_out, " Error\n");
} else {
BIO_printf(bio_s_out, " Keying material: ");
for (i = 0; i < keymatexportlen; i++)
BIO_printf(bio_s_out, "%02X", exportedkeymat[i]);
BIO_printf(bio_s_out, "\n");
}
OPENSSL_free(exportedkeymat);
}
#ifndef OPENSSL_NO_KTLS
if (BIO_get_ktls_send(SSL_get_wbio(con)))
BIO_printf(bio_err, "Using Kernel TLS for sending\n");
if (BIO_get_ktls_recv(SSL_get_rbio(con)))
BIO_printf(bio_err, "Using Kernel TLS for receiving\n");
#endif
(void)BIO_flush(bio_s_out);
}
static int www_body(int s, int stype, int prot, unsigned char *context)
{
char *buf = NULL;
int ret = 1;
int i, j, k, dot;
SSL *con;
const SSL_CIPHER *c;
BIO *io, *ssl_bio, *sbio;
#ifdef RENEG
int total_bytes = 0;
#endif
int width;
#ifndef OPENSSL_NO_KTLS
int use_sendfile_for_req = use_sendfile;
#endif
fd_set readfds;
const char *opmode;
#ifdef CHARSET_EBCDIC
BIO *filter;
#endif
/* Set width for a select call if needed */
width = s + 1;
/* as we use BIO_gets(), and it always null terminates data, we need
* to allocate 1 byte longer buffer to fit the full 2^14 byte record */
buf = app_malloc(bufsize + 1, "server www buffer");
io = BIO_new(BIO_f_buffer());
ssl_bio = BIO_new(BIO_f_ssl());
if ((io == NULL) || (ssl_bio == NULL))
goto err;
if (s_nbio) {
if (!BIO_socket_nbio(s, 1))
ERR_print_errors(bio_err);
else if (!s_quiet)
BIO_printf(bio_err, "Turned on non blocking io\n");
}
/* lets make the output buffer a reasonable size */
if (BIO_set_write_buffer_size(io, bufsize) <= 0)
goto err;
if ((con = SSL_new(ctx)) == NULL)
goto err;
if (s_tlsextdebug) {
SSL_set_tlsext_debug_callback(con, tlsext_cb);
SSL_set_tlsext_debug_arg(con, bio_s_out);
}
if (context != NULL
&& !SSL_set_session_id_context(con, context,
strlen((char *)context))) {
SSL_free(con);
goto err;
}
sbio = BIO_new_socket(s, BIO_NOCLOSE);
if (sbio == NULL) {
SSL_free(con);
goto err;
}
if (s_nbio_test) {
BIO *test;
test = BIO_new(BIO_f_nbio_test());
if (test == NULL) {
SSL_free(con);
BIO_free(sbio);
goto err;
}
sbio = BIO_push(test, sbio);
}
SSL_set_bio(con, sbio, sbio);
SSL_set_accept_state(con);
/* No need to free |con| after this. Done by BIO_free(ssl_bio) */
BIO_set_ssl(ssl_bio, con, BIO_CLOSE);
BIO_push(io, ssl_bio);
ssl_bio = NULL;
#ifdef CHARSET_EBCDIC
filter = BIO_new(BIO_f_ebcdic_filter());
if (filter == NULL)
goto err;
io = BIO_push(filter, io);
#endif
if (s_debug) {
BIO_set_callback_ex(SSL_get_rbio(con), bio_dump_callback);
BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
}
if (s_msg) {
#ifndef OPENSSL_NO_SSL_TRACE
if (s_msg == 2)
SSL_set_msg_callback(con, SSL_trace);
else
#endif
SSL_set_msg_callback(con, msg_cb);
SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out);
}
for (;;) {
i = BIO_gets(io, buf, bufsize + 1);
if (i < 0) { /* error */
if (!BIO_should_retry(io) && !SSL_waiting_for_async(con)) {
if (!s_quiet)
ERR_print_errors(bio_err);
goto err;
} else {
BIO_printf(bio_s_out, "read R BLOCK\n");
#ifndef OPENSSL_NO_SRP
if (BIO_should_io_special(io)
&& BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during read\n");
lookup_srp_user(&srp_callback_parm, bio_s_out);
continue;
}
#endif
ossl_sleep(1000);
continue;
}
} else if (i == 0) { /* end of input */
ret = 1;
goto end;
}
/* else we have data */
if (((www == 1) && (strncmp("GET ", buf, 4) == 0)) ||
((www == 2) && (strncmp("GET /stats ", buf, 11) == 0))) {
char *p;
X509 *peer = NULL;
STACK_OF(SSL_CIPHER) *sk;
static const char *space = " ";
if (www == 1 && strncmp("GET /reneg", buf, 10) == 0) {
if (strncmp("GET /renegcert", buf, 14) == 0)
SSL_set_verify(con,
SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
NULL);
i = SSL_renegotiate(con);
BIO_printf(bio_s_out, "SSL_renegotiate -> %d\n", i);
/* Send the HelloRequest */
i = SSL_do_handshake(con);
if (i <= 0) {
BIO_printf(bio_s_out, "SSL_do_handshake() Retval %d\n",
SSL_get_error(con, i));
ERR_print_errors(bio_err);
goto err;
}
/* Wait for a ClientHello to come back */
FD_ZERO(&readfds);
openssl_fdset(s, &readfds);
i = select(width, (void *)&readfds, NULL, NULL, NULL);
if (i <= 0 || !FD_ISSET(s, &readfds)) {
BIO_printf(bio_s_out,
"Error waiting for client response\n");
ERR_print_errors(bio_err);
goto err;
}
/*
* We're not actually expecting any data here and we ignore
* any that is sent. This is just to force the handshake that
* we're expecting to come from the client. If they haven't
* sent one there's not much we can do.
*/
BIO_gets(io, buf, bufsize + 1);
}
BIO_puts(io,
"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
BIO_puts(io, "<HTML><BODY BGCOLOR=\"#ffffff\">\n");
BIO_puts(io, "<pre>\n");
/* BIO_puts(io, OpenSSL_version(OPENSSL_VERSION)); */
BIO_puts(io, "\n");
for (i = 0; i < local_argc; i++) {
const char *myp;
for (myp = local_argv[i]; *myp; myp++)
switch (*myp) {
case '<':
BIO_puts(io, "&lt;");
break;
case '>':
BIO_puts(io, "&gt;");
break;
case '&':
BIO_puts(io, "&amp;");
break;
default:
BIO_write(io, myp, 1);
break;
}
BIO_write(io, " ", 1);
}
BIO_puts(io, "\n");
BIO_printf(io,
"Secure Renegotiation IS%s supported\n",
SSL_get_secure_renegotiation_support(con) ?
"" : " NOT");
/*
* The following is evil and should not really be done
*/
BIO_printf(io, "Ciphers supported in s_server binary\n");
sk = SSL_get_ciphers(con);
j = sk_SSL_CIPHER_num(sk);
for (i = 0; i < j; i++) {
c = sk_SSL_CIPHER_value(sk, i);
BIO_printf(io, "%-11s:%-25s ",
SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
if ((((i + 1) % 2) == 0) && (i + 1 != j))
BIO_puts(io, "\n");
}
BIO_puts(io, "\n");
p = SSL_get_shared_ciphers(con, buf, bufsize);
if (p != NULL) {
BIO_printf(io,
"---\nCiphers common between both SSL end points:\n");
j = i = 0;
while (*p) {
if (*p == ':') {
BIO_write(io, space, 26 - j);
i++;
j = 0;
BIO_write(io, ((i % 3) ? " " : "\n"), 1);
} else {
BIO_write(io, p, 1);
j++;
}
p++;
}
BIO_puts(io, "\n");
}
ssl_print_sigalgs(io, con);
#ifndef OPENSSL_NO_EC
ssl_print_groups(io, con, 0);
#endif
print_ca_names(io, con);
BIO_printf(io, (SSL_session_reused(con)
? "---\nReused, " : "---\nNew, "));
c = SSL_get_current_cipher(con);
BIO_printf(io, "%s, Cipher is %s\n",
SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
SSL_SESSION_print(io, SSL_get_session(con));
BIO_printf(io, "---\n");
print_stats(io, SSL_get_SSL_CTX(con));
BIO_printf(io, "---\n");
peer = SSL_get0_peer_certificate(con);
if (peer != NULL) {
BIO_printf(io, "Client certificate\n");
X509_print(io, peer);
PEM_write_bio_X509(io, peer);
peer = NULL;
} else {
BIO_puts(io, "no client certificate available\n");
}
BIO_puts(io, "</pre></BODY></HTML>\r\n\r\n");
break;
} else if ((www == 2 || www == 3)
&& (strncmp("GET /", buf, 5) == 0)) {
BIO *file;
char *p, *e;
static const char *text =
"HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n";
/* skip the '/' */
p = &(buf[5]);
dot = 1;
for (e = p; *e != '\0'; e++) {
if (e[0] == ' ')
break;
if (e[0] == ':') {
/* Windows drive. We treat this the same way as ".." */
dot = -1;
break;
}
switch (dot) {
case 1:
dot = (e[0] == '.') ? 2 : 0;
break;
case 2:
dot = (e[0] == '.') ? 3 : 0;
break;
case 3:
dot = (e[0] == '/' || e[0] == '\\') ? -1 : 0;
break;
}
if (dot == 0)
dot = (e[0] == '/' || e[0] == '\\') ? 1 : 0;
}
dot = (dot == 3) || (dot == -1); /* filename contains ".."
* component */
if (*e == '\0') {
BIO_puts(io, text);
BIO_printf(io, "'%s' is an invalid file name\r\n", p);
break;
}
*e = '\0';
if (dot) {
BIO_puts(io, text);
BIO_printf(io, "'%s' contains '..' or ':'\r\n", p);
break;
}
if (*p == '/' || *p == '\\') {
BIO_puts(io, text);
BIO_printf(io, "'%s' is an invalid path\r\n", p);
break;
}
/* if a directory, do the index thang */
if (app_isdir(p) > 0) {
BIO_puts(io, text);
BIO_printf(io, "'%s' is a directory\r\n", p);
break;
}
opmode = (http_server_binmode == 1) ? "rb" : "r";
if ((file = BIO_new_file(p, opmode)) == NULL) {
BIO_puts(io, text);
BIO_printf(io, "Error opening '%s' mode='%s'\r\n", p, opmode);
ERR_print_errors(io);
break;
}
if (!s_quiet)
BIO_printf(bio_err, "FILE:%s\n", p);
if (www == 2) {
i = strlen(p);
if (((i > 5) && (strcmp(&(p[i - 5]), ".html") == 0)) ||
((i > 4) && (strcmp(&(p[i - 4]), ".php") == 0)) ||
((i > 4) && (strcmp(&(p[i - 4]), ".htm") == 0)))
BIO_puts(io,
"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
else
BIO_puts(io,
"HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n");
}
/* send the file */
#ifndef OPENSSL_NO_KTLS
if (use_sendfile_for_req && !BIO_get_ktls_send(SSL_get_wbio(con))) {
BIO_printf(bio_err, "Warning: sendfile requested but KTLS is not available\n");
use_sendfile_for_req = 0;
}
if (use_sendfile_for_req) {
FILE *fp = NULL;
int fd;
struct stat st;
off_t offset = 0;
size_t filesize;
BIO_get_fp(file, &fp);
fd = fileno(fp);
if (fstat(fd, &st) < 0) {
BIO_printf(io, "Error fstat '%s'\r\n", p);
ERR_print_errors(io);
goto write_error;
}
filesize = st.st_size;
if (((int)BIO_flush(io)) < 0)
goto write_error;
for (;;) {
i = SSL_sendfile(con, fd, offset, filesize, 0);
if (i < 0) {
BIO_printf(io, "Error SSL_sendfile '%s'\r\n", p);
ERR_print_errors(io);
break;
} else {
offset += i;
filesize -= i;
}
if (filesize <= 0) {
if (!s_quiet)
BIO_printf(bio_err, "KTLS SENDFILE '%s' OK\n", p);
break;
}
}
} else
#endif
{
for (;;) {
i = BIO_read(file, buf, bufsize);
if (i <= 0)
break;
#ifdef RENEG
total_bytes += i;
BIO_printf(bio_err, "%d\n", i);
if (total_bytes > 3 * 1024) {
total_bytes = 0;
BIO_printf(bio_err, "RENEGOTIATE\n");
SSL_renegotiate(con);
}
#endif
for (j = 0; j < i;) {
#ifdef RENEG
static count = 0;
if (++count == 13)
SSL_renegotiate(con);
#endif
k = BIO_write(io, &(buf[j]), i - j);
if (k <= 0) {
if (!BIO_should_retry(io)
&& !SSL_waiting_for_async(con)) {
goto write_error;
} else {
BIO_printf(bio_s_out, "rwrite W BLOCK\n");
}
} else {
j += k;
}
}
}
}
write_error:
BIO_free(file);
break;
}
}
for (;;) {
i = (int)BIO_flush(io);
if (i <= 0) {
if (!BIO_should_retry(io))
break;
} else
break;
}
end:
/* make sure we re-use sessions */
do_ssl_shutdown(con);
err:
OPENSSL_free(buf);
BIO_free(ssl_bio);
BIO_free_all(io);
return ret;
}
static int rev_body(int s, int stype, int prot, unsigned char *context)
{
char *buf = NULL;
int i;
int ret = 1;
SSL *con;
BIO *io, *ssl_bio, *sbio;
#ifdef CHARSET_EBCDIC
BIO *filter;
#endif
/* as we use BIO_gets(), and it always null terminates data, we need
* to allocate 1 byte longer buffer to fit the full 2^14 byte record */
buf = app_malloc(bufsize + 1, "server rev buffer");
io = BIO_new(BIO_f_buffer());
ssl_bio = BIO_new(BIO_f_ssl());
if ((io == NULL) || (ssl_bio == NULL))
goto err;
/* lets make the output buffer a reasonable size */
if (BIO_set_write_buffer_size(io, bufsize) <= 0)
goto err;
if ((con = SSL_new(ctx)) == NULL)
goto err;
if (s_tlsextdebug) {
SSL_set_tlsext_debug_callback(con, tlsext_cb);
SSL_set_tlsext_debug_arg(con, bio_s_out);
}
if (context != NULL
&& !SSL_set_session_id_context(con, context,
strlen((char *)context))) {
SSL_free(con);
ERR_print_errors(bio_err);
goto err;
}
sbio = BIO_new_socket(s, BIO_NOCLOSE);
if (sbio == NULL) {
SSL_free(con);
ERR_print_errors(bio_err);
goto err;
}
SSL_set_bio(con, sbio, sbio);
SSL_set_accept_state(con);
/* No need to free |con| after this. Done by BIO_free(ssl_bio) */
BIO_set_ssl(ssl_bio, con, BIO_CLOSE);
BIO_push(io, ssl_bio);
ssl_bio = NULL;
#ifdef CHARSET_EBCDIC
filter = BIO_new(BIO_f_ebcdic_filter());
if (filter == NULL)
goto err;
io = BIO_push(filter, io);
#endif
if (s_debug) {
BIO_set_callback_ex(SSL_get_rbio(con), bio_dump_callback);
BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
}
if (s_msg) {
#ifndef OPENSSL_NO_SSL_TRACE
if (s_msg == 2)
SSL_set_msg_callback(con, SSL_trace);
else
#endif
SSL_set_msg_callback(con, msg_cb);
SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out);
}
for (;;) {
i = BIO_do_handshake(io);
if (i > 0)
break;
if (!BIO_should_retry(io)) {
BIO_puts(bio_err, "CONNECTION FAILURE\n");
ERR_print_errors(bio_err);
goto end;
}
#ifndef OPENSSL_NO_SRP
if (BIO_should_io_special(io)
&& BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during accept\n");
lookup_srp_user(&srp_callback_parm, bio_s_out);
continue;
}
#endif
}
BIO_printf(bio_err, "CONNECTION ESTABLISHED\n");
print_ssl_summary(con);
for (;;) {
i = BIO_gets(io, buf, bufsize + 1);
if (i < 0) { /* error */
if (!BIO_should_retry(io)) {
if (!s_quiet)
ERR_print_errors(bio_err);
goto err;
} else {
BIO_printf(bio_s_out, "read R BLOCK\n");
#ifndef OPENSSL_NO_SRP
if (BIO_should_io_special(io)
&& BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
BIO_printf(bio_s_out, "LOOKUP renego during read\n");
lookup_srp_user(&srp_callback_parm, bio_s_out);
continue;
}
#endif
ossl_sleep(1000);
continue;
}
} else if (i == 0) { /* end of input */
ret = 1;
BIO_printf(bio_err, "CONNECTION CLOSED\n");
goto end;
} else {
char *p = buf + i - 1;
while (i && (*p == '\n' || *p == '\r')) {
p--;
i--;
}
if (!s_ign_eof && (i == 5) && (strncmp(buf, "CLOSE", 5) == 0)) {
ret = 1;
BIO_printf(bio_err, "CONNECTION CLOSED\n");
goto end;
}
BUF_reverse((unsigned char *)buf, NULL, i);
buf[i] = '\n';
BIO_write(io, buf, i + 1);
for (;;) {
i = BIO_flush(io);
if (i > 0)
break;
if (!BIO_should_retry(io))
goto end;
}
}
}
end:
/* make sure we re-use sessions */
do_ssl_shutdown(con);
err:
OPENSSL_free(buf);
BIO_free(ssl_bio);
BIO_free_all(io);
return ret;
}
#define MAX_SESSION_ID_ATTEMPTS 10
static int generate_session_id(SSL *ssl, unsigned char *id,
unsigned int *id_len)
{
unsigned int count = 0;
unsigned int session_id_prefix_len = strlen(session_id_prefix);
do {
if (RAND_bytes(id, *id_len) <= 0)
return 0;
/*
* Prefix the session_id with the required prefix. NB: If our prefix
* is too long, clip it - but there will be worse effects anyway, eg.
* the server could only possibly create 1 session ID (ie. the
* prefix!) so all future session negotiations will fail due to
* conflicts.
*/
memcpy(id, session_id_prefix,
(session_id_prefix_len < *id_len) ?
session_id_prefix_len : *id_len);
}
while (SSL_has_matching_session_id(ssl, id, *id_len) &&
(++count < MAX_SESSION_ID_ATTEMPTS));
if (count >= MAX_SESSION_ID_ATTEMPTS)
return 0;
return 1;
}
/*
* By default s_server uses an in-memory cache which caches SSL_SESSION
* structures without any serialization. This hides some bugs which only
* become apparent in deployed servers. By implementing a basic external
* session cache some issues can be debugged using s_server.
*/
typedef struct simple_ssl_session_st {
unsigned char *id;
unsigned int idlen;
unsigned char *der;
int derlen;
struct simple_ssl_session_st *next;
} simple_ssl_session;
static simple_ssl_session *first = NULL;
static int add_session(SSL *ssl, SSL_SESSION *session)
{
simple_ssl_session *sess = app_malloc(sizeof(*sess), "get session");
unsigned char *p;
SSL_SESSION_get_id(session, &sess->idlen);
sess->derlen = i2d_SSL_SESSION(session, NULL);
if (sess->derlen < 0) {
BIO_printf(bio_err, "Error encoding session\n");
OPENSSL_free(sess);
return 0;
}
sess->id = OPENSSL_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen);
sess->der = app_malloc(sess->derlen, "get session buffer");
if (!sess->id) {
BIO_printf(bio_err, "Out of memory adding to external cache\n");
OPENSSL_free(sess->id);
OPENSSL_free(sess->der);
OPENSSL_free(sess);
return 0;
}
p = sess->der;
/* Assume it still works. */
if (i2d_SSL_SESSION(session, &p) != sess->derlen) {
BIO_printf(bio_err, "Unexpected session encoding length\n");
OPENSSL_free(sess->id);
OPENSSL_free(sess->der);
OPENSSL_free(sess);
return 0;
}
sess->next = first;
first = sess;
BIO_printf(bio_err, "New session added to external cache\n");
return 0;
}
static SSL_SESSION *get_session(SSL *ssl, const unsigned char *id, int idlen,
int *do_copy)
{
simple_ssl_session *sess;
*do_copy = 0;
for (sess = first; sess; sess = sess->next) {
if (idlen == (int)sess->idlen && !memcmp(sess->id, id, idlen)) {
const unsigned char *p = sess->der;
BIO_printf(bio_err, "Lookup session: cache hit\n");
return d2i_SSL_SESSION(NULL, &p, sess->derlen);
}
}
BIO_printf(bio_err, "Lookup session: cache miss\n");
return NULL;
}
static void del_session(SSL_CTX *sctx, SSL_SESSION *session)
{
simple_ssl_session *sess, *prev = NULL;
const unsigned char *id;
unsigned int idlen;
id = SSL_SESSION_get_id(session, &idlen);
for (sess = first; sess; sess = sess->next) {
if (idlen == sess->idlen && !memcmp(sess->id, id, idlen)) {
if (prev)
prev->next = sess->next;
else
first = sess->next;
OPENSSL_free(sess->id);
OPENSSL_free(sess->der);
OPENSSL_free(sess);
return;
}
prev = sess;
}
}
static void init_session_cache_ctx(SSL_CTX *sctx)
{
SSL_CTX_set_session_cache_mode(sctx,
SSL_SESS_CACHE_NO_INTERNAL |
SSL_SESS_CACHE_SERVER);
SSL_CTX_sess_set_new_cb(sctx, add_session);
SSL_CTX_sess_set_get_cb(sctx, get_session);
SSL_CTX_sess_set_remove_cb(sctx, del_session);
}
static void free_sessions(void)
{
simple_ssl_session *sess, *tsess;
for (sess = first; sess;) {
OPENSSL_free(sess->id);
OPENSSL_free(sess->der);
tsess = sess;
sess = sess->next;
OPENSSL_free(tsess);
}
first = NULL;
}
#endif /* OPENSSL_NO_SOCK */
diff --git a/crypto/aes/asm/aesv8-armx.pl b/crypto/aes/asm/aesv8-armx.pl
index 6a7bf05d1b35..544dc7e8effe 100755
--- a/crypto/aes/asm/aesv8-armx.pl
+++ b/crypto/aes/asm/aesv8-armx.pl
@@ -1,3734 +1,3736 @@
#! /usr/bin/env perl
-# Copyright 2014-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2014-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
#
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# project. The module is, however, dual licensed under OpenSSL and
# CRYPTOGAMS licenses depending on where you obtain it. For further
# details see http://www.openssl.org/~appro/cryptogams/.
# ====================================================================
#
# This module implements support for ARMv8 AES instructions. The
# module is endian-agnostic in sense that it supports both big- and
# little-endian cases. As does it support both 32- and 64-bit modes
# of operation. Latter is achieved by limiting amount of utilized
# registers to 16, which implies additional NEON load and integer
# instructions. This has no effect on mighty Apple A7, where results
# are literally equal to the theoretical estimates based on AES
# instruction latencies and issue rates. On Cortex-A53, an in-order
# execution core, this costs up to 10-15%, which is partially
# compensated by implementing dedicated code path for 128-bit
# CBC encrypt case. On Cortex-A57 parallelizable mode performance
# seems to be limited by sheer amount of NEON instructions...
#
# April 2019
#
# Key to performance of parallelize-able modes is round instruction
# interleaving. But which factor to use? There is optimal one for
# each combination of instruction latency and issue rate, beyond
# which increasing interleave factor doesn't pay off. While on cons
# side we have code size increase and resource waste on platforms for
# which interleave factor is too high. In other words you want it to
# be just right. So far interleave factor of 3x was serving well all
# platforms. But for ThunderX2 optimal interleave factor was measured
# to be 5x...
#
# Performance in cycles per byte processed with 128-bit key:
#
# CBC enc CBC dec CTR
# Apple A7 2.39 1.20 1.20
# Cortex-A53 1.32 1.17/1.29(**) 1.36/1.46
# Cortex-A57(*) 1.95 0.82/0.85 0.89/0.93
# Cortex-A72 1.33 0.85/0.88 0.92/0.96
# Denver 1.96 0.65/0.86 0.76/0.80
# Mongoose 1.33 1.23/1.20 1.30/1.20
# Kryo 1.26 0.87/0.94 1.00/1.00
# ThunderX2 5.95 1.25 1.30
#
# (*) original 3.64/1.34/1.32 results were for r0p0 revision
# and are still same even for updated module;
# (**) numbers after slash are for 32-bit code, which is 3x-
# interleaved;
# $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
$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
$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: $!";
*STDOUT=*OUT;
$prefix="aes_v8";
$_byte = ($flavour =~ /win/ ? "DCB" : ".byte");
$code=<<___;
#include "arm_arch.h"
#if __ARM_MAX_ARCH__>=7
___
$code.=".arch armv8-a+crypto\n.text\n" if ($flavour =~ /64/);
$code.=<<___ if ($flavour !~ /64/);
.arch armv7-a // don't confuse not-so-latest binutils with argv8 :-)
.fpu neon
#ifdef __thumb2__
.syntax unified
.thumb
# define INST(a,b,c,d) $_byte c,d|0xc,a,b
#else
.code 32
# define INST(a,b,c,d) $_byte a,b,c,d
#endif
.text
___
# Assembler mnemonics are an eclectic mix of 32- and 64-bit syntax,
# NEON is mostly 32-bit mnemonics, integer - mostly 64. Goal is to
# maintain both 32- and 64-bit codes within single module and
# transliterate common code to either flavour with regex vodoo.
#
{{{
my ($inp,$bits,$out,$ptr,$rounds)=("x0","w1","x2","x3","w12");
my ($zero,$rcon,$mask,$in0,$in1,$tmp,$key)=
$flavour=~/64/? map("q$_",(0..6)) : map("q$_",(0..3,8..10));
$code.=<<___;
.align 5
.Lrcon:
.long 0x01,0x01,0x01,0x01
.long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d // rotate-n-splat
.long 0x1b,0x1b,0x1b,0x1b
.globl ${prefix}_set_encrypt_key
.type ${prefix}_set_encrypt_key,%function
.align 5
${prefix}_set_encrypt_key:
.Lenc_key:
___
$code.=<<___ if ($flavour =~ /64/);
stp x29,x30,[sp,#-16]!
add x29,sp,#0
___
$code.=<<___;
mov $ptr,#-1
cmp $inp,#0
b.eq .Lenc_key_abort
cmp $out,#0
b.eq .Lenc_key_abort
mov $ptr,#-2
cmp $bits,#128
b.lt .Lenc_key_abort
cmp $bits,#256
b.gt .Lenc_key_abort
tst $bits,#0x3f
b.ne .Lenc_key_abort
adr $ptr,.Lrcon
cmp $bits,#192
veor $zero,$zero,$zero
vld1.8 {$in0},[$inp],#16
mov $bits,#8 // reuse $bits
vld1.32 {$rcon,$mask},[$ptr],#32
b.lt .Loop128
b.eq .L192
b .L256
.align 4
.Loop128:
vtbl.8 $key,{$in0},$mask
vext.8 $tmp,$zero,$in0,#12
vst1.32 {$in0},[$out],#16
aese $key,$zero
subs $bits,$bits,#1
veor $in0,$in0,$tmp
vext.8 $tmp,$zero,$tmp,#12
veor $in0,$in0,$tmp
vext.8 $tmp,$zero,$tmp,#12
veor $key,$key,$rcon
veor $in0,$in0,$tmp
vshl.u8 $rcon,$rcon,#1
veor $in0,$in0,$key
b.ne .Loop128
vld1.32 {$rcon},[$ptr]
vtbl.8 $key,{$in0},$mask
vext.8 $tmp,$zero,$in0,#12
vst1.32 {$in0},[$out],#16
aese $key,$zero
veor $in0,$in0,$tmp
vext.8 $tmp,$zero,$tmp,#12
veor $in0,$in0,$tmp
vext.8 $tmp,$zero,$tmp,#12
veor $key,$key,$rcon
veor $in0,$in0,$tmp
vshl.u8 $rcon,$rcon,#1
veor $in0,$in0,$key
vtbl.8 $key,{$in0},$mask
vext.8 $tmp,$zero,$in0,#12
vst1.32 {$in0},[$out],#16
aese $key,$zero
veor $in0,$in0,$tmp
vext.8 $tmp,$zero,$tmp,#12
veor $in0,$in0,$tmp
vext.8 $tmp,$zero,$tmp,#12
veor $key,$key,$rcon
veor $in0,$in0,$tmp
veor $in0,$in0,$key
vst1.32 {$in0},[$out]
add $out,$out,#0x50
mov $rounds,#10
b .Ldone
.align 4
.L192:
vld1.8 {$in1},[$inp],#8
vmov.i8 $key,#8 // borrow $key
vst1.32 {$in0},[$out],#16
vsub.i8 $mask,$mask,$key // adjust the mask
.Loop192:
vtbl.8 $key,{$in1},$mask
vext.8 $tmp,$zero,$in0,#12
#ifdef __ARMEB__
vst1.32 {$in1},[$out],#16
sub $out,$out,#8
#else
vst1.32 {$in1},[$out],#8
#endif
aese $key,$zero
subs $bits,$bits,#1
veor $in0,$in0,$tmp
vext.8 $tmp,$zero,$tmp,#12
veor $in0,$in0,$tmp
vext.8 $tmp,$zero,$tmp,#12
veor $in0,$in0,$tmp
vdup.32 $tmp,${in0}[3]
veor $tmp,$tmp,$in1
veor $key,$key,$rcon
vext.8 $in1,$zero,$in1,#12
vshl.u8 $rcon,$rcon,#1
veor $in1,$in1,$tmp
veor $in0,$in0,$key
veor $in1,$in1,$key
vst1.32 {$in0},[$out],#16
b.ne .Loop192
mov $rounds,#12
add $out,$out,#0x20
b .Ldone
.align 4
.L256:
vld1.8 {$in1},[$inp]
mov $bits,#7
mov $rounds,#14
vst1.32 {$in0},[$out],#16
.Loop256:
vtbl.8 $key,{$in1},$mask
vext.8 $tmp,$zero,$in0,#12
vst1.32 {$in1},[$out],#16
aese $key,$zero
subs $bits,$bits,#1
veor $in0,$in0,$tmp
vext.8 $tmp,$zero,$tmp,#12
veor $in0,$in0,$tmp
vext.8 $tmp,$zero,$tmp,#12
veor $key,$key,$rcon
veor $in0,$in0,$tmp
vshl.u8 $rcon,$rcon,#1
veor $in0,$in0,$key
vst1.32 {$in0},[$out],#16
b.eq .Ldone
vdup.32 $key,${in0}[3] // just splat
vext.8 $tmp,$zero,$in1,#12
aese $key,$zero
veor $in1,$in1,$tmp
vext.8 $tmp,$zero,$tmp,#12
veor $in1,$in1,$tmp
vext.8 $tmp,$zero,$tmp,#12
veor $in1,$in1,$tmp
veor $in1,$in1,$key
b .Loop256
.Ldone:
str $rounds,[$out]
mov $ptr,#0
.Lenc_key_abort:
mov x0,$ptr // return value
`"ldr x29,[sp],#16" if ($flavour =~ /64/)`
ret
.size ${prefix}_set_encrypt_key,.-${prefix}_set_encrypt_key
.globl ${prefix}_set_decrypt_key
.type ${prefix}_set_decrypt_key,%function
.align 5
${prefix}_set_decrypt_key:
___
$code.=<<___ if ($flavour =~ /64/);
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
___
$code.=<<___ if ($flavour !~ /64/);
stmdb sp!,{r4,lr}
___
$code.=<<___;
bl .Lenc_key
cmp x0,#0
b.ne .Ldec_key_abort
sub $out,$out,#240 // restore original $out
mov x4,#-16
add $inp,$out,x12,lsl#4 // end of key schedule
vld1.32 {v0.16b},[$out]
vld1.32 {v1.16b},[$inp]
vst1.32 {v0.16b},[$inp],x4
vst1.32 {v1.16b},[$out],#16
.Loop_imc:
vld1.32 {v0.16b},[$out]
vld1.32 {v1.16b},[$inp]
aesimc v0.16b,v0.16b
aesimc v1.16b,v1.16b
vst1.32 {v0.16b},[$inp],x4
vst1.32 {v1.16b},[$out],#16
cmp $inp,$out
b.hi .Loop_imc
vld1.32 {v0.16b},[$out]
aesimc v0.16b,v0.16b
vst1.32 {v0.16b},[$inp]
eor x0,x0,x0 // return value
.Ldec_key_abort:
___
$code.=<<___ if ($flavour !~ /64/);
ldmia sp!,{r4,pc}
___
$code.=<<___ if ($flavour =~ /64/);
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
___
$code.=<<___;
.size ${prefix}_set_decrypt_key,.-${prefix}_set_decrypt_key
___
}}}
{{{
sub gen_block () {
my $dir = shift;
my ($e,$mc) = $dir eq "en" ? ("e","mc") : ("d","imc");
my ($inp,$out,$key)=map("x$_",(0..2));
my $rounds="w3";
my ($rndkey0,$rndkey1,$inout)=map("q$_",(0..3));
$code.=<<___;
.globl ${prefix}_${dir}crypt
.type ${prefix}_${dir}crypt,%function
.align 5
${prefix}_${dir}crypt:
ldr $rounds,[$key,#240]
vld1.32 {$rndkey0},[$key],#16
vld1.8 {$inout},[$inp]
sub $rounds,$rounds,#2
vld1.32 {$rndkey1},[$key],#16
.Loop_${dir}c:
aes$e $inout,$rndkey0
aes$mc $inout,$inout
vld1.32 {$rndkey0},[$key],#16
subs $rounds,$rounds,#2
aes$e $inout,$rndkey1
aes$mc $inout,$inout
vld1.32 {$rndkey1},[$key],#16
b.gt .Loop_${dir}c
aes$e $inout,$rndkey0
aes$mc $inout,$inout
vld1.32 {$rndkey0},[$key]
aes$e $inout,$rndkey1
veor $inout,$inout,$rndkey0
vst1.8 {$inout},[$out]
ret
.size ${prefix}_${dir}crypt,.-${prefix}_${dir}crypt
___
}
&gen_block("en");
&gen_block("de");
}}}
# Performance in cycles per byte.
# Processed with AES-ECB different key size.
# It shows the value before and after optimization as below:
# (before/after):
#
# AES-128-ECB AES-192-ECB AES-256-ECB
# Cortex-A57 1.85/0.82 2.16/0.96 2.47/1.10
# Cortex-A72 1.64/0.85 1.82/0.99 2.13/1.14
# Optimization is implemented by loop unrolling and interleaving.
# Commonly, we choose the unrolling factor as 5, if the input
# data size smaller than 5 blocks, but not smaller than 3 blocks,
# choose 3 as the unrolling factor.
# If the input data size dsize >= 5*16 bytes, then take 5 blocks
# as one iteration, every loop the left size lsize -= 5*16.
# If 5*16 > lsize >= 3*16 bytes, take 3 blocks as one iteration,
# every loop lsize -=3*16.
# If lsize < 3*16 bytes, treat them as the tail, interleave the
# two blocks AES instructions.
# There is one special case, if the original input data size dsize
# = 16 bytes, we will treat it seperately to improve the
# performance: one independent code block without LR, FP load and
# store, just looks like what the original ECB implementation does.
{{{
my ($inp,$out,$len,$key)=map("x$_",(0..3));
my ($enc,$rounds,$cnt,$key_,$step)=("w4","w5","w6","x7","x8");
my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$tmp2,$rndlast)=map("q$_",(0..7));
my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1);
### q7 last round key
### q10-q15 q7 Last 7 round keys
### q8-q9 preloaded round keys except last 7 keys for big size
### q5, q6, q8-q9 preloaded round keys except last 7 keys for only 16 byte
{
my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
my ($dat3,$in3,$tmp3); # used only in 64-bit mode
my ($dat4,$in4,$tmp4);
if ($flavour =~ /64/) {
($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23));
}
$code.=<<___;
.globl ${prefix}_ecb_encrypt
.type ${prefix}_ecb_encrypt,%function
.align 5
${prefix}_ecb_encrypt:
___
$code.=<<___ if ($flavour =~ /64/);
subs $len,$len,#16
// Original input data size bigger than 16, jump to big size processing.
b.ne .Lecb_big_size
vld1.8 {$dat0},[$inp]
cmp $enc,#0 // en- or decrypting?
ldr $rounds,[$key,#240]
vld1.32 {q5-q6},[$key],#32 // load key schedule...
b.eq .Lecb_small_dec
aese $dat0,q5
aesmc $dat0,$dat0
vld1.32 {q8-q9},[$key],#32 // load key schedule...
aese $dat0,q6
aesmc $dat0,$dat0
subs $rounds,$rounds,#10 // if rounds==10, jump to aes-128-ecb processing
b.eq .Lecb_128_enc
.Lecb_round_loop:
aese $dat0,q8
aesmc $dat0,$dat0
vld1.32 {q8},[$key],#16 // load key schedule...
aese $dat0,q9
aesmc $dat0,$dat0
vld1.32 {q9},[$key],#16 // load key schedule...
subs $rounds,$rounds,#2 // bias
b.gt .Lecb_round_loop
.Lecb_128_enc:
vld1.32 {q10-q11},[$key],#32 // load key schedule...
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat0,q9
aesmc $dat0,$dat0
vld1.32 {q12-q13},[$key],#32 // load key schedule...
aese $dat0,q10
aesmc $dat0,$dat0
aese $dat0,q11
aesmc $dat0,$dat0
vld1.32 {q14-q15},[$key],#32 // load key schedule...
aese $dat0,q12
aesmc $dat0,$dat0
aese $dat0,q13
aesmc $dat0,$dat0
vld1.32 {$rndlast},[$key]
aese $dat0,q14
aesmc $dat0,$dat0
aese $dat0,q15
veor $dat0,$dat0,$rndlast
vst1.8 {$dat0},[$out]
b .Lecb_Final_abort
.Lecb_small_dec:
aesd $dat0,q5
aesimc $dat0,$dat0
vld1.32 {q8-q9},[$key],#32 // load key schedule...
aesd $dat0,q6
aesimc $dat0,$dat0
subs $rounds,$rounds,#10 // bias
b.eq .Lecb_128_dec
.Lecb_dec_round_loop:
aesd $dat0,q8
aesimc $dat0,$dat0
vld1.32 {q8},[$key],#16 // load key schedule...
aesd $dat0,q9
aesimc $dat0,$dat0
vld1.32 {q9},[$key],#16 // load key schedule...
subs $rounds,$rounds,#2 // bias
b.gt .Lecb_dec_round_loop
.Lecb_128_dec:
vld1.32 {q10-q11},[$key],#32 // load key schedule...
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat0,q9
aesimc $dat0,$dat0
vld1.32 {q12-q13},[$key],#32 // load key schedule...
aesd $dat0,q10
aesimc $dat0,$dat0
aesd $dat0,q11
aesimc $dat0,$dat0
vld1.32 {q14-q15},[$key],#32 // load key schedule...
aesd $dat0,q12
aesimc $dat0,$dat0
aesd $dat0,q13
aesimc $dat0,$dat0
vld1.32 {$rndlast},[$key]
aesd $dat0,q14
aesimc $dat0,$dat0
aesd $dat0,q15
veor $dat0,$dat0,$rndlast
vst1.8 {$dat0},[$out]
b .Lecb_Final_abort
.Lecb_big_size:
___
$code.=<<___ if ($flavour =~ /64/);
stp x29,x30,[sp,#-16]!
add x29,sp,#0
___
$code.=<<___ if ($flavour !~ /64/);
mov ip,sp
stmdb sp!,{r4-r8,lr}
vstmdb sp!,{d8-d15} @ ABI specification says so
ldmia ip,{r4-r5} @ load remaining args
subs $len,$len,#16
___
$code.=<<___;
mov $step,#16
b.lo .Lecb_done
cclr $step,eq
cmp $enc,#0 // en- or decrypting?
ldr $rounds,[$key,#240]
and $len,$len,#-16
vld1.8 {$dat},[$inp],$step
vld1.32 {q8-q9},[$key] // load key schedule...
sub $rounds,$rounds,#6
add $key_,$key,x5,lsl#4 // pointer to last 7 round keys
sub $rounds,$rounds,#2
vld1.32 {q10-q11},[$key_],#32
vld1.32 {q12-q13},[$key_],#32
vld1.32 {q14-q15},[$key_],#32
vld1.32 {$rndlast},[$key_]
add $key_,$key,#32
mov $cnt,$rounds
b.eq .Lecb_dec
vld1.8 {$dat1},[$inp],#16
subs $len,$len,#32 // bias
add $cnt,$rounds,#2
vorr $in1,$dat1,$dat1
vorr $dat2,$dat1,$dat1
vorr $dat1,$dat,$dat
b.lo .Lecb_enc_tail
vorr $dat1,$in1,$in1
vld1.8 {$dat2},[$inp],#16
___
$code.=<<___ if ($flavour =~ /64/);
cmp $len,#32
b.lo .Loop3x_ecb_enc
vld1.8 {$dat3},[$inp],#16
vld1.8 {$dat4},[$inp],#16
sub $len,$len,#32 // bias
mov $cnt,$rounds
.Loop5x_ecb_enc:
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
aese $dat3,q8
aesmc $dat3,$dat3
aese $dat4,q8
aesmc $dat4,$dat4
vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aese $dat0,q9
aesmc $dat0,$dat0
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
aese $dat3,q9
aesmc $dat3,$dat3
aese $dat4,q9
aesmc $dat4,$dat4
vld1.32 {q9},[$key_],#16
b.gt .Loop5x_ecb_enc
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
aese $dat3,q8
aesmc $dat3,$dat3
aese $dat4,q8
aesmc $dat4,$dat4
cmp $len,#0x40 // because .Lecb_enc_tail4x
sub $len,$len,#0x50
aese $dat0,q9
aesmc $dat0,$dat0
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
aese $dat3,q9
aesmc $dat3,$dat3
aese $dat4,q9
aesmc $dat4,$dat4
csel x6,xzr,$len,gt // borrow x6, $cnt, "gt" is not typo
mov $key_,$key
aese $dat0,q10
aesmc $dat0,$dat0
aese $dat1,q10
aesmc $dat1,$dat1
aese $dat2,q10
aesmc $dat2,$dat2
aese $dat3,q10
aesmc $dat3,$dat3
aese $dat4,q10
aesmc $dat4,$dat4
add $inp,$inp,x6 // $inp is adjusted in such way that
// at exit from the loop $dat1-$dat4
// are loaded with last "words"
add x6,$len,#0x60 // because .Lecb_enc_tail4x
aese $dat0,q11
aesmc $dat0,$dat0
aese $dat1,q11
aesmc $dat1,$dat1
aese $dat2,q11
aesmc $dat2,$dat2
aese $dat3,q11
aesmc $dat3,$dat3
aese $dat4,q11
aesmc $dat4,$dat4
aese $dat0,q12
aesmc $dat0,$dat0
aese $dat1,q12
aesmc $dat1,$dat1
aese $dat2,q12
aesmc $dat2,$dat2
aese $dat3,q12
aesmc $dat3,$dat3
aese $dat4,q12
aesmc $dat4,$dat4
aese $dat0,q13
aesmc $dat0,$dat0
aese $dat1,q13
aesmc $dat1,$dat1
aese $dat2,q13
aesmc $dat2,$dat2
aese $dat3,q13
aesmc $dat3,$dat3
aese $dat4,q13
aesmc $dat4,$dat4
aese $dat0,q14
aesmc $dat0,$dat0
aese $dat1,q14
aesmc $dat1,$dat1
aese $dat2,q14
aesmc $dat2,$dat2
aese $dat3,q14
aesmc $dat3,$dat3
aese $dat4,q14
aesmc $dat4,$dat4
aese $dat0,q15
vld1.8 {$in0},[$inp],#16
aese $dat1,q15
vld1.8 {$in1},[$inp],#16
aese $dat2,q15
vld1.8 {$in2},[$inp],#16
aese $dat3,q15
vld1.8 {$in3},[$inp],#16
aese $dat4,q15
vld1.8 {$in4},[$inp],#16
cbz x6,.Lecb_enc_tail4x
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
veor $tmp0,$rndlast,$dat0
vorr $dat0,$in0,$in0
veor $tmp1,$rndlast,$dat1
vorr $dat1,$in1,$in1
veor $tmp2,$rndlast,$dat2
vorr $dat2,$in2,$in2
veor $tmp3,$rndlast,$dat3
vorr $dat3,$in3,$in3
veor $tmp4,$rndlast,$dat4
vst1.8 {$tmp0},[$out],#16
vorr $dat4,$in4,$in4
vst1.8 {$tmp1},[$out],#16
mov $cnt,$rounds
vst1.8 {$tmp2},[$out],#16
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
vst1.8 {$tmp3},[$out],#16
vst1.8 {$tmp4},[$out],#16
b.hs .Loop5x_ecb_enc
add $len,$len,#0x50
cbz $len,.Lecb_done
add $cnt,$rounds,#2
subs $len,$len,#0x30
vorr $dat0,$in2,$in2
vorr $dat1,$in3,$in3
vorr $dat2,$in4,$in4
b.lo .Lecb_enc_tail
b .Loop3x_ecb_enc
.align 4
.Lecb_enc_tail4x:
veor $tmp1,$rndlast,$dat1
veor $tmp2,$rndlast,$dat2
veor $tmp3,$rndlast,$dat3
veor $tmp4,$rndlast,$dat4
vst1.8 {$tmp1},[$out],#16
vst1.8 {$tmp2},[$out],#16
vst1.8 {$tmp3},[$out],#16
vst1.8 {$tmp4},[$out],#16
b .Lecb_done
.align 4
___
$code.=<<___;
.Loop3x_ecb_enc:
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aese $dat0,q9
aesmc $dat0,$dat0
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
vld1.32 {q9},[$key_],#16
b.gt .Loop3x_ecb_enc
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
subs $len,$len,#0x30
mov.lo x6,$len // x6, $cnt, is zero at this point
aese $dat0,q9
aesmc $dat0,$dat0
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
add $inp,$inp,x6 // $inp is adjusted in such way that
// at exit from the loop $dat1-$dat2
// are loaded with last "words"
mov $key_,$key
aese $dat0,q12
aesmc $dat0,$dat0
aese $dat1,q12
aesmc $dat1,$dat1
aese $dat2,q12
aesmc $dat2,$dat2
vld1.8 {$in0},[$inp],#16
aese $dat0,q13
aesmc $dat0,$dat0
aese $dat1,q13
aesmc $dat1,$dat1
aese $dat2,q13
aesmc $dat2,$dat2
vld1.8 {$in1},[$inp],#16
aese $dat0,q14
aesmc $dat0,$dat0
aese $dat1,q14
aesmc $dat1,$dat1
aese $dat2,q14
aesmc $dat2,$dat2
vld1.8 {$in2},[$inp],#16
aese $dat0,q15
aese $dat1,q15
aese $dat2,q15
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
add $cnt,$rounds,#2
veor $tmp0,$rndlast,$dat0
veor $tmp1,$rndlast,$dat1
veor $dat2,$dat2,$rndlast
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
vst1.8 {$tmp0},[$out],#16
vorr $dat0,$in0,$in0
vst1.8 {$tmp1},[$out],#16
vorr $dat1,$in1,$in1
vst1.8 {$dat2},[$out],#16
vorr $dat2,$in2,$in2
b.hs .Loop3x_ecb_enc
cmn $len,#0x30
b.eq .Lecb_done
nop
.Lecb_enc_tail:
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
vld1.32 {q9},[$key_],#16
b.gt .Lecb_enc_tail
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
aese $dat1,q12
aesmc $dat1,$dat1
aese $dat2,q12
aesmc $dat2,$dat2
cmn $len,#0x20
aese $dat1,q13
aesmc $dat1,$dat1
aese $dat2,q13
aesmc $dat2,$dat2
aese $dat1,q14
aesmc $dat1,$dat1
aese $dat2,q14
aesmc $dat2,$dat2
aese $dat1,q15
aese $dat2,q15
b.eq .Lecb_enc_one
veor $tmp1,$rndlast,$dat1
veor $tmp2,$rndlast,$dat2
vst1.8 {$tmp1},[$out],#16
vst1.8 {$tmp2},[$out],#16
b .Lecb_done
.Lecb_enc_one:
veor $tmp1,$rndlast,$dat2
vst1.8 {$tmp1},[$out],#16
b .Lecb_done
___
$code.=<<___;
.align 5
.Lecb_dec:
vld1.8 {$dat1},[$inp],#16
subs $len,$len,#32 // bias
add $cnt,$rounds,#2
vorr $in1,$dat1,$dat1
vorr $dat2,$dat1,$dat1
vorr $dat1,$dat,$dat
b.lo .Lecb_dec_tail
vorr $dat1,$in1,$in1
vld1.8 {$dat2},[$inp],#16
___
$code.=<<___ if ($flavour =~ /64/);
cmp $len,#32
b.lo .Loop3x_ecb_dec
vld1.8 {$dat3},[$inp],#16
vld1.8 {$dat4},[$inp],#16
sub $len,$len,#32 // bias
mov $cnt,$rounds
.Loop5x_ecb_dec:
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
aesd $dat3,q8
aesimc $dat3,$dat3
aesd $dat4,q8
aesimc $dat4,$dat4
vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aesd $dat0,q9
aesimc $dat0,$dat0
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
aesd $dat3,q9
aesimc $dat3,$dat3
aesd $dat4,q9
aesimc $dat4,$dat4
vld1.32 {q9},[$key_],#16
b.gt .Loop5x_ecb_dec
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
aesd $dat3,q8
aesimc $dat3,$dat3
aesd $dat4,q8
aesimc $dat4,$dat4
cmp $len,#0x40 // because .Lecb_tail4x
sub $len,$len,#0x50
aesd $dat0,q9
aesimc $dat0,$dat0
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
aesd $dat3,q9
aesimc $dat3,$dat3
aesd $dat4,q9
aesimc $dat4,$dat4
csel x6,xzr,$len,gt // borrow x6, $cnt, "gt" is not typo
mov $key_,$key
aesd $dat0,q10
aesimc $dat0,$dat0
aesd $dat1,q10
aesimc $dat1,$dat1
aesd $dat2,q10
aesimc $dat2,$dat2
aesd $dat3,q10
aesimc $dat3,$dat3
aesd $dat4,q10
aesimc $dat4,$dat4
add $inp,$inp,x6 // $inp is adjusted in such way that
// at exit from the loop $dat1-$dat4
// are loaded with last "words"
add x6,$len,#0x60 // because .Lecb_tail4x
aesd $dat0,q11
aesimc $dat0,$dat0
aesd $dat1,q11
aesimc $dat1,$dat1
aesd $dat2,q11
aesimc $dat2,$dat2
aesd $dat3,q11
aesimc $dat3,$dat3
aesd $dat4,q11
aesimc $dat4,$dat4
aesd $dat0,q12
aesimc $dat0,$dat0
aesd $dat1,q12
aesimc $dat1,$dat1
aesd $dat2,q12
aesimc $dat2,$dat2
aesd $dat3,q12
aesimc $dat3,$dat3
aesd $dat4,q12
aesimc $dat4,$dat4
aesd $dat0,q13
aesimc $dat0,$dat0
aesd $dat1,q13
aesimc $dat1,$dat1
aesd $dat2,q13
aesimc $dat2,$dat2
aesd $dat3,q13
aesimc $dat3,$dat3
aesd $dat4,q13
aesimc $dat4,$dat4
aesd $dat0,q14
aesimc $dat0,$dat0
aesd $dat1,q14
aesimc $dat1,$dat1
aesd $dat2,q14
aesimc $dat2,$dat2
aesd $dat3,q14
aesimc $dat3,$dat3
aesd $dat4,q14
aesimc $dat4,$dat4
aesd $dat0,q15
vld1.8 {$in0},[$inp],#16
aesd $dat1,q15
vld1.8 {$in1},[$inp],#16
aesd $dat2,q15
vld1.8 {$in2},[$inp],#16
aesd $dat3,q15
vld1.8 {$in3},[$inp],#16
aesd $dat4,q15
vld1.8 {$in4},[$inp],#16
cbz x6,.Lecb_tail4x
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
veor $tmp0,$rndlast,$dat0
vorr $dat0,$in0,$in0
veor $tmp1,$rndlast,$dat1
vorr $dat1,$in1,$in1
veor $tmp2,$rndlast,$dat2
vorr $dat2,$in2,$in2
veor $tmp3,$rndlast,$dat3
vorr $dat3,$in3,$in3
veor $tmp4,$rndlast,$dat4
vst1.8 {$tmp0},[$out],#16
vorr $dat4,$in4,$in4
vst1.8 {$tmp1},[$out],#16
mov $cnt,$rounds
vst1.8 {$tmp2},[$out],#16
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
vst1.8 {$tmp3},[$out],#16
vst1.8 {$tmp4},[$out],#16
b.hs .Loop5x_ecb_dec
add $len,$len,#0x50
cbz $len,.Lecb_done
add $cnt,$rounds,#2
subs $len,$len,#0x30
vorr $dat0,$in2,$in2
vorr $dat1,$in3,$in3
vorr $dat2,$in4,$in4
b.lo .Lecb_dec_tail
b .Loop3x_ecb_dec
.align 4
.Lecb_tail4x:
veor $tmp1,$rndlast,$dat1
veor $tmp2,$rndlast,$dat2
veor $tmp3,$rndlast,$dat3
veor $tmp4,$rndlast,$dat4
vst1.8 {$tmp1},[$out],#16
vst1.8 {$tmp2},[$out],#16
vst1.8 {$tmp3},[$out],#16
vst1.8 {$tmp4},[$out],#16
b .Lecb_done
.align 4
___
$code.=<<___;
.Loop3x_ecb_dec:
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aesd $dat0,q9
aesimc $dat0,$dat0
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
vld1.32 {q9},[$key_],#16
b.gt .Loop3x_ecb_dec
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
subs $len,$len,#0x30
mov.lo x6,$len // x6, $cnt, is zero at this point
aesd $dat0,q9
aesimc $dat0,$dat0
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
add $inp,$inp,x6 // $inp is adjusted in such way that
// at exit from the loop $dat1-$dat2
// are loaded with last "words"
mov $key_,$key
aesd $dat0,q12
aesimc $dat0,$dat0
aesd $dat1,q12
aesimc $dat1,$dat1
aesd $dat2,q12
aesimc $dat2,$dat2
vld1.8 {$in0},[$inp],#16
aesd $dat0,q13
aesimc $dat0,$dat0
aesd $dat1,q13
aesimc $dat1,$dat1
aesd $dat2,q13
aesimc $dat2,$dat2
vld1.8 {$in1},[$inp],#16
aesd $dat0,q14
aesimc $dat0,$dat0
aesd $dat1,q14
aesimc $dat1,$dat1
aesd $dat2,q14
aesimc $dat2,$dat2
vld1.8 {$in2},[$inp],#16
aesd $dat0,q15
aesd $dat1,q15
aesd $dat2,q15
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
add $cnt,$rounds,#2
veor $tmp0,$rndlast,$dat0
veor $tmp1,$rndlast,$dat1
veor $dat2,$dat2,$rndlast
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
vst1.8 {$tmp0},[$out],#16
vorr $dat0,$in0,$in0
vst1.8 {$tmp1},[$out],#16
vorr $dat1,$in1,$in1
vst1.8 {$dat2},[$out],#16
vorr $dat2,$in2,$in2
b.hs .Loop3x_ecb_dec
cmn $len,#0x30
b.eq .Lecb_done
nop
.Lecb_dec_tail:
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
vld1.32 {q9},[$key_],#16
b.gt .Lecb_dec_tail
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
aesd $dat1,q12
aesimc $dat1,$dat1
aesd $dat2,q12
aesimc $dat2,$dat2
cmn $len,#0x20
aesd $dat1,q13
aesimc $dat1,$dat1
aesd $dat2,q13
aesimc $dat2,$dat2
aesd $dat1,q14
aesimc $dat1,$dat1
aesd $dat2,q14
aesimc $dat2,$dat2
aesd $dat1,q15
aesd $dat2,q15
b.eq .Lecb_dec_one
veor $tmp1,$rndlast,$dat1
veor $tmp2,$rndlast,$dat2
vst1.8 {$tmp1},[$out],#16
vst1.8 {$tmp2},[$out],#16
b .Lecb_done
.Lecb_dec_one:
veor $tmp1,$rndlast,$dat2
vst1.8 {$tmp1},[$out],#16
.Lecb_done:
___
}
$code.=<<___ if ($flavour !~ /64/);
vldmia sp!,{d8-d15}
ldmia sp!,{r4-r8,pc}
___
$code.=<<___ if ($flavour =~ /64/);
ldr x29,[sp],#16
___
$code.=<<___ if ($flavour =~ /64/);
.Lecb_Final_abort:
ret
___
$code.=<<___;
.size ${prefix}_ecb_encrypt,.-${prefix}_ecb_encrypt
___
}}}
{{{
my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4)); my $enc="w5";
my ($rounds,$cnt,$key_,$step,$step1)=($enc,"w6","x7","x8","x12");
my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7));
my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1);
my ($key4,$key5,$key6,$key7)=("x6","x12","x14",$key);
### q8-q15 preloaded key schedule
$code.=<<___;
.globl ${prefix}_cbc_encrypt
.type ${prefix}_cbc_encrypt,%function
.align 5
${prefix}_cbc_encrypt:
___
$code.=<<___ if ($flavour =~ /64/);
stp x29,x30,[sp,#-16]!
add x29,sp,#0
___
$code.=<<___ if ($flavour !~ /64/);
mov ip,sp
stmdb sp!,{r4-r8,lr}
vstmdb sp!,{d8-d15} @ ABI specification says so
ldmia ip,{r4-r5} @ load remaining args
___
$code.=<<___;
subs $len,$len,#16
mov $step,#16
b.lo .Lcbc_abort
cclr $step,eq
cmp $enc,#0 // en- or decrypting?
ldr $rounds,[$key,#240]
and $len,$len,#-16
vld1.8 {$ivec},[$ivp]
vld1.8 {$dat},[$inp],$step
vld1.32 {q8-q9},[$key] // load key schedule...
sub $rounds,$rounds,#6
add $key_,$key,x5,lsl#4 // pointer to last 7 round keys
sub $rounds,$rounds,#2
vld1.32 {q10-q11},[$key_],#32
vld1.32 {q12-q13},[$key_],#32
vld1.32 {q14-q15},[$key_],#32
vld1.32 {$rndlast},[$key_]
add $key_,$key,#32
mov $cnt,$rounds
b.eq .Lcbc_dec
cmp $rounds,#2
veor $dat,$dat,$ivec
veor $rndzero_n_last,q8,$rndlast
b.eq .Lcbc_enc128
vld1.32 {$in0-$in1},[$key_]
add $key_,$key,#16
add $key4,$key,#16*4
add $key5,$key,#16*5
aese $dat,q8
aesmc $dat,$dat
add $key6,$key,#16*6
add $key7,$key,#16*7
b .Lenter_cbc_enc
.align 4
.Loop_cbc_enc:
aese $dat,q8
aesmc $dat,$dat
vst1.8 {$ivec},[$out],#16
.Lenter_cbc_enc:
aese $dat,q9
aesmc $dat,$dat
aese $dat,$in0
aesmc $dat,$dat
vld1.32 {q8},[$key4]
cmp $rounds,#4
aese $dat,$in1
aesmc $dat,$dat
vld1.32 {q9},[$key5]
b.eq .Lcbc_enc192
aese $dat,q8
aesmc $dat,$dat
vld1.32 {q8},[$key6]
aese $dat,q9
aesmc $dat,$dat
vld1.32 {q9},[$key7]
nop
.Lcbc_enc192:
aese $dat,q8
aesmc $dat,$dat
subs $len,$len,#16
aese $dat,q9
aesmc $dat,$dat
cclr $step,eq
aese $dat,q10
aesmc $dat,$dat
aese $dat,q11
aesmc $dat,$dat
vld1.8 {q8},[$inp],$step
aese $dat,q12
aesmc $dat,$dat
veor q8,q8,$rndzero_n_last
aese $dat,q13
aesmc $dat,$dat
vld1.32 {q9},[$key_] // re-pre-load rndkey[1]
aese $dat,q14
aesmc $dat,$dat
aese $dat,q15
veor $ivec,$dat,$rndlast
b.hs .Loop_cbc_enc
vst1.8 {$ivec},[$out],#16
b .Lcbc_done
.align 5
.Lcbc_enc128:
vld1.32 {$in0-$in1},[$key_]
aese $dat,q8
aesmc $dat,$dat
b .Lenter_cbc_enc128
.Loop_cbc_enc128:
aese $dat,q8
aesmc $dat,$dat
vst1.8 {$ivec},[$out],#16
.Lenter_cbc_enc128:
aese $dat,q9
aesmc $dat,$dat
subs $len,$len,#16
aese $dat,$in0
aesmc $dat,$dat
cclr $step,eq
aese $dat,$in1
aesmc $dat,$dat
aese $dat,q10
aesmc $dat,$dat
aese $dat,q11
aesmc $dat,$dat
vld1.8 {q8},[$inp],$step
aese $dat,q12
aesmc $dat,$dat
aese $dat,q13
aesmc $dat,$dat
aese $dat,q14
aesmc $dat,$dat
veor q8,q8,$rndzero_n_last
aese $dat,q15
veor $ivec,$dat,$rndlast
b.hs .Loop_cbc_enc128
vst1.8 {$ivec},[$out],#16
b .Lcbc_done
___
{
my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
my ($dat3,$in3,$tmp3); # used only in 64-bit mode
my ($dat4,$in4,$tmp4);
if ($flavour =~ /64/) {
($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23));
}
$code.=<<___;
.align 5
.Lcbc_dec:
vld1.8 {$dat2},[$inp],#16
subs $len,$len,#32 // bias
add $cnt,$rounds,#2
vorr $in1,$dat,$dat
vorr $dat1,$dat,$dat
vorr $in2,$dat2,$dat2
b.lo .Lcbc_dec_tail
vorr $dat1,$dat2,$dat2
vld1.8 {$dat2},[$inp],#16
vorr $in0,$dat,$dat
vorr $in1,$dat1,$dat1
vorr $in2,$dat2,$dat2
___
$code.=<<___ if ($flavour =~ /64/);
cmp $len,#32
b.lo .Loop3x_cbc_dec
vld1.8 {$dat3},[$inp],#16
vld1.8 {$dat4},[$inp],#16
sub $len,$len,#32 // bias
mov $cnt,$rounds
vorr $in3,$dat3,$dat3
vorr $in4,$dat4,$dat4
.Loop5x_cbc_dec:
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
aesd $dat3,q8
aesimc $dat3,$dat3
aesd $dat4,q8
aesimc $dat4,$dat4
vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aesd $dat0,q9
aesimc $dat0,$dat0
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
aesd $dat3,q9
aesimc $dat3,$dat3
aesd $dat4,q9
aesimc $dat4,$dat4
vld1.32 {q9},[$key_],#16
b.gt .Loop5x_cbc_dec
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
aesd $dat3,q8
aesimc $dat3,$dat3
aesd $dat4,q8
aesimc $dat4,$dat4
cmp $len,#0x40 // because .Lcbc_tail4x
sub $len,$len,#0x50
aesd $dat0,q9
aesimc $dat0,$dat0
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
aesd $dat3,q9
aesimc $dat3,$dat3
aesd $dat4,q9
aesimc $dat4,$dat4
csel x6,xzr,$len,gt // borrow x6, $cnt, "gt" is not typo
mov $key_,$key
aesd $dat0,q10
aesimc $dat0,$dat0
aesd $dat1,q10
aesimc $dat1,$dat1
aesd $dat2,q10
aesimc $dat2,$dat2
aesd $dat3,q10
aesimc $dat3,$dat3
aesd $dat4,q10
aesimc $dat4,$dat4
add $inp,$inp,x6 // $inp is adjusted in such way that
// at exit from the loop $dat1-$dat4
// are loaded with last "words"
add x6,$len,#0x60 // because .Lcbc_tail4x
aesd $dat0,q11
aesimc $dat0,$dat0
aesd $dat1,q11
aesimc $dat1,$dat1
aesd $dat2,q11
aesimc $dat2,$dat2
aesd $dat3,q11
aesimc $dat3,$dat3
aesd $dat4,q11
aesimc $dat4,$dat4
aesd $dat0,q12
aesimc $dat0,$dat0
aesd $dat1,q12
aesimc $dat1,$dat1
aesd $dat2,q12
aesimc $dat2,$dat2
aesd $dat3,q12
aesimc $dat3,$dat3
aesd $dat4,q12
aesimc $dat4,$dat4
aesd $dat0,q13
aesimc $dat0,$dat0
aesd $dat1,q13
aesimc $dat1,$dat1
aesd $dat2,q13
aesimc $dat2,$dat2
aesd $dat3,q13
aesimc $dat3,$dat3
aesd $dat4,q13
aesimc $dat4,$dat4
aesd $dat0,q14
aesimc $dat0,$dat0
aesd $dat1,q14
aesimc $dat1,$dat1
aesd $dat2,q14
aesimc $dat2,$dat2
aesd $dat3,q14
aesimc $dat3,$dat3
aesd $dat4,q14
aesimc $dat4,$dat4
veor $tmp0,$ivec,$rndlast
aesd $dat0,q15
veor $tmp1,$in0,$rndlast
vld1.8 {$in0},[$inp],#16
aesd $dat1,q15
veor $tmp2,$in1,$rndlast
vld1.8 {$in1},[$inp],#16
aesd $dat2,q15
veor $tmp3,$in2,$rndlast
vld1.8 {$in2},[$inp],#16
aesd $dat3,q15
veor $tmp4,$in3,$rndlast
vld1.8 {$in3},[$inp],#16
aesd $dat4,q15
vorr $ivec,$in4,$in4
vld1.8 {$in4},[$inp],#16
cbz x6,.Lcbc_tail4x
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
veor $tmp0,$tmp0,$dat0
vorr $dat0,$in0,$in0
veor $tmp1,$tmp1,$dat1
vorr $dat1,$in1,$in1
veor $tmp2,$tmp2,$dat2
vorr $dat2,$in2,$in2
veor $tmp3,$tmp3,$dat3
vorr $dat3,$in3,$in3
veor $tmp4,$tmp4,$dat4
vst1.8 {$tmp0},[$out],#16
vorr $dat4,$in4,$in4
vst1.8 {$tmp1},[$out],#16
mov $cnt,$rounds
vst1.8 {$tmp2},[$out],#16
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
vst1.8 {$tmp3},[$out],#16
vst1.8 {$tmp4},[$out],#16
b.hs .Loop5x_cbc_dec
add $len,$len,#0x50
cbz $len,.Lcbc_done
add $cnt,$rounds,#2
subs $len,$len,#0x30
vorr $dat0,$in2,$in2
vorr $in0,$in2,$in2
vorr $dat1,$in3,$in3
vorr $in1,$in3,$in3
vorr $dat2,$in4,$in4
vorr $in2,$in4,$in4
b.lo .Lcbc_dec_tail
b .Loop3x_cbc_dec
.align 4
.Lcbc_tail4x:
veor $tmp1,$tmp0,$dat1
veor $tmp2,$tmp2,$dat2
veor $tmp3,$tmp3,$dat3
veor $tmp4,$tmp4,$dat4
vst1.8 {$tmp1},[$out],#16
vst1.8 {$tmp2},[$out],#16
vst1.8 {$tmp3},[$out],#16
vst1.8 {$tmp4},[$out],#16
b .Lcbc_done
.align 4
___
$code.=<<___;
.Loop3x_cbc_dec:
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aesd $dat0,q9
aesimc $dat0,$dat0
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
vld1.32 {q9},[$key_],#16
b.gt .Loop3x_cbc_dec
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
veor $tmp0,$ivec,$rndlast
subs $len,$len,#0x30
veor $tmp1,$in0,$rndlast
mov.lo x6,$len // x6, $cnt, is zero at this point
aesd $dat0,q9
aesimc $dat0,$dat0
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
veor $tmp2,$in1,$rndlast
add $inp,$inp,x6 // $inp is adjusted in such way that
// at exit from the loop $dat1-$dat2
// are loaded with last "words"
vorr $ivec,$in2,$in2
mov $key_,$key
aesd $dat0,q12
aesimc $dat0,$dat0
aesd $dat1,q12
aesimc $dat1,$dat1
aesd $dat2,q12
aesimc $dat2,$dat2
vld1.8 {$in0},[$inp],#16
aesd $dat0,q13
aesimc $dat0,$dat0
aesd $dat1,q13
aesimc $dat1,$dat1
aesd $dat2,q13
aesimc $dat2,$dat2
vld1.8 {$in1},[$inp],#16
aesd $dat0,q14
aesimc $dat0,$dat0
aesd $dat1,q14
aesimc $dat1,$dat1
aesd $dat2,q14
aesimc $dat2,$dat2
vld1.8 {$in2},[$inp],#16
aesd $dat0,q15
aesd $dat1,q15
aesd $dat2,q15
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
add $cnt,$rounds,#2
veor $tmp0,$tmp0,$dat0
veor $tmp1,$tmp1,$dat1
veor $dat2,$dat2,$tmp2
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
vst1.8 {$tmp0},[$out],#16
vorr $dat0,$in0,$in0
vst1.8 {$tmp1},[$out],#16
vorr $dat1,$in1,$in1
vst1.8 {$dat2},[$out],#16
vorr $dat2,$in2,$in2
b.hs .Loop3x_cbc_dec
cmn $len,#0x30
b.eq .Lcbc_done
nop
.Lcbc_dec_tail:
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
vld1.32 {q9},[$key_],#16
b.gt .Lcbc_dec_tail
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
aesd $dat1,q12
aesimc $dat1,$dat1
aesd $dat2,q12
aesimc $dat2,$dat2
cmn $len,#0x20
aesd $dat1,q13
aesimc $dat1,$dat1
aesd $dat2,q13
aesimc $dat2,$dat2
veor $tmp1,$ivec,$rndlast
aesd $dat1,q14
aesimc $dat1,$dat1
aesd $dat2,q14
aesimc $dat2,$dat2
veor $tmp2,$in1,$rndlast
aesd $dat1,q15
aesd $dat2,q15
b.eq .Lcbc_dec_one
veor $tmp1,$tmp1,$dat1
veor $tmp2,$tmp2,$dat2
vorr $ivec,$in2,$in2
vst1.8 {$tmp1},[$out],#16
vst1.8 {$tmp2},[$out],#16
b .Lcbc_done
.Lcbc_dec_one:
veor $tmp1,$tmp1,$dat2
vorr $ivec,$in2,$in2
vst1.8 {$tmp1},[$out],#16
.Lcbc_done:
vst1.8 {$ivec},[$ivp]
.Lcbc_abort:
___
}
$code.=<<___ if ($flavour !~ /64/);
vldmia sp!,{d8-d15}
ldmia sp!,{r4-r8,pc}
___
$code.=<<___ if ($flavour =~ /64/);
ldr x29,[sp],#16
ret
___
$code.=<<___;
.size ${prefix}_cbc_encrypt,.-${prefix}_cbc_encrypt
___
}}}
{{{
my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4));
my ($rounds,$cnt,$key_)=("w5","w6","x7");
my ($ctr,$tctr0,$tctr1,$tctr2)=map("w$_",(8..10,12));
my $step="x12"; # aliases with $tctr2
my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7));
my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
# used only in 64-bit mode...
my ($dat3,$dat4,$in3,$in4)=map("q$_",(16..23));
my ($dat,$tmp)=($dat0,$tmp0);
### q8-q15 preloaded key schedule
$code.=<<___;
.globl ${prefix}_ctr32_encrypt_blocks
.type ${prefix}_ctr32_encrypt_blocks,%function
.align 5
${prefix}_ctr32_encrypt_blocks:
___
$code.=<<___ if ($flavour =~ /64/);
stp x29,x30,[sp,#-16]!
add x29,sp,#0
___
$code.=<<___ if ($flavour !~ /64/);
mov ip,sp
stmdb sp!,{r4-r10,lr}
vstmdb sp!,{d8-d15} @ ABI specification says so
ldr r4, [ip] @ load remaining arg
___
$code.=<<___;
ldr $rounds,[$key,#240]
ldr $ctr, [$ivp, #12]
#ifdef __ARMEB__
vld1.8 {$dat0},[$ivp]
#else
vld1.32 {$dat0},[$ivp]
#endif
vld1.32 {q8-q9},[$key] // load key schedule...
sub $rounds,$rounds,#4
mov $step,#16
cmp $len,#2
add $key_,$key,x5,lsl#4 // pointer to last 5 round keys
sub $rounds,$rounds,#2
vld1.32 {q12-q13},[$key_],#32
vld1.32 {q14-q15},[$key_],#32
vld1.32 {$rndlast},[$key_]
add $key_,$key,#32
mov $cnt,$rounds
cclr $step,lo
#ifndef __ARMEB__
rev $ctr, $ctr
#endif
___
$code.=<<___ if ($flavour =~ /64/);
vorr $dat1,$dat0,$dat0
add $tctr1, $ctr, #1
vorr $dat2,$dat0,$dat0
add $ctr, $ctr, #2
vorr $ivec,$dat0,$dat0
rev $tctr1, $tctr1
vmov.32 ${dat1}[3],$tctr1
b.ls .Lctr32_tail
rev $tctr2, $ctr
sub $len,$len,#3 // bias
vmov.32 ${dat2}[3],$tctr2
___
$code.=<<___ if ($flavour !~ /64/);
add $tctr1, $ctr, #1
vorr $ivec,$dat0,$dat0
rev $tctr1, $tctr1
vmov.32 ${ivec}[3],$tctr1
add $ctr, $ctr, #2
vorr $dat1,$ivec,$ivec
b.ls .Lctr32_tail
rev $tctr2, $ctr
vmov.32 ${ivec}[3],$tctr2
sub $len,$len,#3 // bias
vorr $dat2,$ivec,$ivec
___
$code.=<<___ if ($flavour =~ /64/);
cmp $len,#32
b.lo .Loop3x_ctr32
add w13,$ctr,#1
add w14,$ctr,#2
vorr $dat3,$dat0,$dat0
rev w13,w13
vorr $dat4,$dat0,$dat0
rev w14,w14
vmov.32 ${dat3}[3],w13
sub $len,$len,#2 // bias
vmov.32 ${dat4}[3],w14
add $ctr,$ctr,#2
b .Loop5x_ctr32
.align 4
.Loop5x_ctr32:
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
aese $dat3,q8
aesmc $dat3,$dat3
aese $dat4,q8
aesmc $dat4,$dat4
vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aese $dat0,q9
aesmc $dat0,$dat0
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
aese $dat3,q9
aesmc $dat3,$dat3
aese $dat4,q9
aesmc $dat4,$dat4
vld1.32 {q9},[$key_],#16
b.gt .Loop5x_ctr32
mov $key_,$key
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
aese $dat3,q8
aesmc $dat3,$dat3
aese $dat4,q8
aesmc $dat4,$dat4
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
aese $dat0,q9
aesmc $dat0,$dat0
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
aese $dat3,q9
aesmc $dat3,$dat3
aese $dat4,q9
aesmc $dat4,$dat4
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
aese $dat0,q12
aesmc $dat0,$dat0
add $tctr0,$ctr,#1
add $tctr1,$ctr,#2
aese $dat1,q12
aesmc $dat1,$dat1
add $tctr2,$ctr,#3
add w13,$ctr,#4
aese $dat2,q12
aesmc $dat2,$dat2
add w14,$ctr,#5
rev $tctr0,$tctr0
aese $dat3,q12
aesmc $dat3,$dat3
rev $tctr1,$tctr1
rev $tctr2,$tctr2
aese $dat4,q12
aesmc $dat4,$dat4
rev w13,w13
rev w14,w14
aese $dat0,q13
aesmc $dat0,$dat0
aese $dat1,q13
aesmc $dat1,$dat1
aese $dat2,q13
aesmc $dat2,$dat2
aese $dat3,q13
aesmc $dat3,$dat3
aese $dat4,q13
aesmc $dat4,$dat4
aese $dat0,q14
aesmc $dat0,$dat0
vld1.8 {$in0},[$inp],#16
aese $dat1,q14
aesmc $dat1,$dat1
vld1.8 {$in1},[$inp],#16
aese $dat2,q14
aesmc $dat2,$dat2
vld1.8 {$in2},[$inp],#16
aese $dat3,q14
aesmc $dat3,$dat3
vld1.8 {$in3},[$inp],#16
aese $dat4,q14
aesmc $dat4,$dat4
vld1.8 {$in4},[$inp],#16
aese $dat0,q15
veor $in0,$in0,$rndlast
aese $dat1,q15
veor $in1,$in1,$rndlast
aese $dat2,q15
veor $in2,$in2,$rndlast
aese $dat3,q15
veor $in3,$in3,$rndlast
aese $dat4,q15
veor $in4,$in4,$rndlast
veor $in0,$in0,$dat0
vorr $dat0,$ivec,$ivec
veor $in1,$in1,$dat1
vorr $dat1,$ivec,$ivec
veor $in2,$in2,$dat2
vorr $dat2,$ivec,$ivec
veor $in3,$in3,$dat3
vorr $dat3,$ivec,$ivec
veor $in4,$in4,$dat4
vorr $dat4,$ivec,$ivec
vst1.8 {$in0},[$out],#16
vmov.32 ${dat0}[3],$tctr0
vst1.8 {$in1},[$out],#16
vmov.32 ${dat1}[3],$tctr1
vst1.8 {$in2},[$out],#16
vmov.32 ${dat2}[3],$tctr2
vst1.8 {$in3},[$out],#16
vmov.32 ${dat3}[3],w13
vst1.8 {$in4},[$out],#16
vmov.32 ${dat4}[3],w14
mov $cnt,$rounds
cbz $len,.Lctr32_done
add $ctr,$ctr,#5
subs $len,$len,#5
b.hs .Loop5x_ctr32
add $len,$len,#5
sub $ctr,$ctr,#5
cmp $len,#2
mov $step,#16
cclr $step,lo
b.ls .Lctr32_tail
sub $len,$len,#3 // bias
add $ctr,$ctr,#3
___
$code.=<<___;
b .Loop3x_ctr32
.align 4
.Loop3x_ctr32:
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aese $dat0,q9
aesmc $dat0,$dat0
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
vld1.32 {q9},[$key_],#16
b.gt .Loop3x_ctr32
aese $dat0,q8
aesmc $tmp0,$dat0
aese $dat1,q8
aesmc $tmp1,$dat1
vld1.8 {$in0},[$inp],#16
___
$code.=<<___ if ($flavour =~ /64/);
vorr $dat0,$ivec,$ivec
___
$code.=<<___ if ($flavour !~ /64/);
add $tctr0,$ctr,#1
___
$code.=<<___;
aese $dat2,q8
aesmc $dat2,$dat2
vld1.8 {$in1},[$inp],#16
___
$code.=<<___ if ($flavour =~ /64/);
vorr $dat1,$ivec,$ivec
___
$code.=<<___ if ($flavour !~ /64/);
rev $tctr0,$tctr0
___
$code.=<<___;
aese $tmp0,q9
aesmc $tmp0,$tmp0
aese $tmp1,q9
aesmc $tmp1,$tmp1
vld1.8 {$in2},[$inp],#16
mov $key_,$key
aese $dat2,q9
aesmc $tmp2,$dat2
___
$code.=<<___ if ($flavour =~ /64/);
vorr $dat2,$ivec,$ivec
add $tctr0,$ctr,#1
___
$code.=<<___;
aese $tmp0,q12
aesmc $tmp0,$tmp0
aese $tmp1,q12
aesmc $tmp1,$tmp1
veor $in0,$in0,$rndlast
add $tctr1,$ctr,#2
aese $tmp2,q12
aesmc $tmp2,$tmp2
veor $in1,$in1,$rndlast
add $ctr,$ctr,#3
aese $tmp0,q13
aesmc $tmp0,$tmp0
aese $tmp1,q13
aesmc $tmp1,$tmp1
veor $in2,$in2,$rndlast
___
$code.=<<___ if ($flavour =~ /64/);
rev $tctr0,$tctr0
aese $tmp2,q13
aesmc $tmp2,$tmp2
vmov.32 ${dat0}[3], $tctr0
___
$code.=<<___ if ($flavour !~ /64/);
vmov.32 ${ivec}[3], $tctr0
aese $tmp2,q13
aesmc $tmp2,$tmp2
vorr $dat0,$ivec,$ivec
___
$code.=<<___;
rev $tctr1,$tctr1
aese $tmp0,q14
aesmc $tmp0,$tmp0
___
$code.=<<___ if ($flavour !~ /64/);
vmov.32 ${ivec}[3], $tctr1
rev $tctr2,$ctr
___
$code.=<<___;
aese $tmp1,q14
aesmc $tmp1,$tmp1
___
$code.=<<___ if ($flavour =~ /64/);
vmov.32 ${dat1}[3], $tctr1
rev $tctr2,$ctr
aese $tmp2,q14
aesmc $tmp2,$tmp2
vmov.32 ${dat2}[3], $tctr2
___
$code.=<<___ if ($flavour !~ /64/);
vorr $dat1,$ivec,$ivec
vmov.32 ${ivec}[3], $tctr2
aese $tmp2,q14
aesmc $tmp2,$tmp2
vorr $dat2,$ivec,$ivec
___
$code.=<<___;
subs $len,$len,#3
aese $tmp0,q15
aese $tmp1,q15
aese $tmp2,q15
veor $in0,$in0,$tmp0
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
vst1.8 {$in0},[$out],#16
veor $in1,$in1,$tmp1
mov $cnt,$rounds
vst1.8 {$in1},[$out],#16
veor $in2,$in2,$tmp2
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
vst1.8 {$in2},[$out],#16
b.hs .Loop3x_ctr32
adds $len,$len,#3
b.eq .Lctr32_done
cmp $len,#1
mov $step,#16
cclr $step,eq
.Lctr32_tail:
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat1,q8
aesmc $dat1,$dat1
vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aese $dat0,q9
aesmc $dat0,$dat0
aese $dat1,q9
aesmc $dat1,$dat1
vld1.32 {q9},[$key_],#16
b.gt .Lctr32_tail
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat0,q9
aesmc $dat0,$dat0
aese $dat1,q9
aesmc $dat1,$dat1
vld1.8 {$in0},[$inp],$step
aese $dat0,q12
aesmc $dat0,$dat0
aese $dat1,q12
aesmc $dat1,$dat1
vld1.8 {$in1},[$inp]
aese $dat0,q13
aesmc $dat0,$dat0
aese $dat1,q13
aesmc $dat1,$dat1
veor $in0,$in0,$rndlast
aese $dat0,q14
aesmc $dat0,$dat0
aese $dat1,q14
aesmc $dat1,$dat1
veor $in1,$in1,$rndlast
aese $dat0,q15
aese $dat1,q15
cmp $len,#1
veor $in0,$in0,$dat0
veor $in1,$in1,$dat1
vst1.8 {$in0},[$out],#16
b.eq .Lctr32_done
vst1.8 {$in1},[$out]
.Lctr32_done:
___
$code.=<<___ if ($flavour !~ /64/);
vldmia sp!,{d8-d15}
ldmia sp!,{r4-r10,pc}
___
$code.=<<___ if ($flavour =~ /64/);
ldr x29,[sp],#16
ret
___
$code.=<<___;
.size ${prefix}_ctr32_encrypt_blocks,.-${prefix}_ctr32_encrypt_blocks
___
}}}
# Performance in cycles per byte.
# Processed with AES-XTS different key size.
# It shows the value before and after optimization as below:
# (before/after):
#
# AES-128-XTS AES-256-XTS
# Cortex-A57 3.36/1.09 4.02/1.37
# Cortex-A72 3.03/1.02 3.28/1.33
# Optimization is implemented by loop unrolling and interleaving.
# Commonly, we choose the unrolling factor as 5, if the input
# data size smaller than 5 blocks, but not smaller than 3 blocks,
# choose 3 as the unrolling factor.
# If the input data size dsize >= 5*16 bytes, then take 5 blocks
# as one iteration, every loop the left size lsize -= 5*16.
# If lsize < 5*16 bytes, treat them as the tail. Note: left 4*16 bytes
# will be processed specially, which be integrated into the 5*16 bytes
# loop to improve the efficiency.
# There is one special case, if the original input data size dsize
# = 16 bytes, we will treat it seperately to improve the
# performance: one independent code block without LR, FP load and
# store.
# Encryption will process the (length -tailcnt) bytes as mentioned
# previously, then encrypt the composite block as last second
# cipher block.
# Decryption will process the (length -tailcnt -1) bytes as mentioned
# previously, then decrypt the last second cipher block to get the
# last plain block(tail), decrypt the composite block as last second
# plain text block.
{{{
my ($inp,$out,$len,$key1,$key2,$ivp)=map("x$_",(0..5));
my ($rounds0,$rounds,$key_,$step,$ivl,$ivh)=("w5","w6","x7","x8","x9","x10");
my ($tmpoutp,$loutp,$l2outp,$tmpinp)=("x13","w14","w15","x20");
my ($tailcnt,$midnum,$midnumx,$constnum,$constnumx)=("x21","w22","x22","w19","x19");
my ($xoffset,$tmpmx,$tmpmw)=("x6","x11","w11");
my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$tmp2,$rndlast)=map("q$_",(0..7));
my ($iv0,$iv1,$iv2,$iv3,$iv4)=("v6.16b","v8.16b","v9.16b","v10.16b","v11.16b");
my ($ivd00,$ivd01,$ivd20,$ivd21)=("d6","v6.d[1]","d9","v9.d[1]");
my ($ivd10,$ivd11,$ivd30,$ivd31,$ivd40,$ivd41)=("d8","v8.d[1]","d10","v10.d[1]","d11","v11.d[1]");
my ($tmpin)=("v26.16b");
my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1);
# q7 last round key
# q10-q15, q7 Last 7 round keys
# q8-q9 preloaded round keys except last 7 keys for big size
# q20, q21, q8-q9 preloaded round keys except last 7 keys for only 16 byte
my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
my ($dat3,$in3,$tmp3); # used only in 64-bit mode
my ($dat4,$in4,$tmp4);
if ($flavour =~ /64/) {
($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23));
}
$code.=<<___ if ($flavour =~ /64/);
.globl ${prefix}_xts_encrypt
.type ${prefix}_xts_encrypt,%function
.align 5
${prefix}_xts_encrypt:
___
$code.=<<___ if ($flavour =~ /64/);
cmp $len,#16
// Original input data size bigger than 16, jump to big size processing.
b.ne .Lxts_enc_big_size
// Encrypt the iv with key2, as the first XEX iv.
ldr $rounds,[$key2,#240]
- vld1.8 {$dat},[$key2],#16
+ vld1.32 {$dat},[$key2],#16
vld1.8 {$iv0},[$ivp]
sub $rounds,$rounds,#2
- vld1.8 {$dat1},[$key2],#16
+ vld1.32 {$dat1},[$key2],#16
.Loop_enc_iv_enc:
aese $iv0,$dat
aesmc $iv0,$iv0
vld1.32 {$dat},[$key2],#16
subs $rounds,$rounds,#2
aese $iv0,$dat1
aesmc $iv0,$iv0
vld1.32 {$dat1},[$key2],#16
b.gt .Loop_enc_iv_enc
aese $iv0,$dat
aesmc $iv0,$iv0
vld1.32 {$dat},[$key2]
aese $iv0,$dat1
veor $iv0,$iv0,$dat
vld1.8 {$dat0},[$inp]
veor $dat0,$iv0,$dat0
ldr $rounds,[$key1,#240]
vld1.32 {q20-q21},[$key1],#32 // load key schedule...
aese $dat0,q20
aesmc $dat0,$dat0
vld1.32 {q8-q9},[$key1],#32 // load key schedule...
aese $dat0,q21
aesmc $dat0,$dat0
subs $rounds,$rounds,#10 // if rounds==10, jump to aes-128-xts processing
b.eq .Lxts_128_enc
.Lxts_enc_round_loop:
aese $dat0,q8
aesmc $dat0,$dat0
vld1.32 {q8},[$key1],#16 // load key schedule...
aese $dat0,q9
aesmc $dat0,$dat0
vld1.32 {q9},[$key1],#16 // load key schedule...
subs $rounds,$rounds,#2 // bias
b.gt .Lxts_enc_round_loop
.Lxts_128_enc:
vld1.32 {q10-q11},[$key1],#32 // load key schedule...
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat0,q9
aesmc $dat0,$dat0
vld1.32 {q12-q13},[$key1],#32 // load key schedule...
aese $dat0,q10
aesmc $dat0,$dat0
aese $dat0,q11
aesmc $dat0,$dat0
vld1.32 {q14-q15},[$key1],#32 // load key schedule...
aese $dat0,q12
aesmc $dat0,$dat0
aese $dat0,q13
aesmc $dat0,$dat0
vld1.32 {$rndlast},[$key1]
aese $dat0,q14
aesmc $dat0,$dat0
aese $dat0,q15
veor $dat0,$dat0,$rndlast
veor $dat0,$dat0,$iv0
vst1.8 {$dat0},[$out]
b .Lxts_enc_final_abort
.align 4
.Lxts_enc_big_size:
___
$code.=<<___ if ($flavour =~ /64/);
stp $constnumx,$tmpinp,[sp,#-64]!
stp $tailcnt,$midnumx,[sp,#48]
stp $ivd10,$ivd20,[sp,#32]
stp $ivd30,$ivd40,[sp,#16]
// tailcnt store the tail value of length%16.
and $tailcnt,$len,#0xf
and $len,$len,#-16
subs $len,$len,#16
mov $step,#16
b.lo .Lxts_abort
csel $step,xzr,$step,eq
// Firstly, encrypt the iv with key2, as the first iv of XEX.
ldr $rounds,[$key2,#240]
vld1.32 {$dat},[$key2],#16
vld1.8 {$iv0},[$ivp]
sub $rounds,$rounds,#2
vld1.32 {$dat1},[$key2],#16
.Loop_iv_enc:
aese $iv0,$dat
aesmc $iv0,$iv0
vld1.32 {$dat},[$key2],#16
subs $rounds,$rounds,#2
aese $iv0,$dat1
aesmc $iv0,$iv0
vld1.32 {$dat1},[$key2],#16
b.gt .Loop_iv_enc
aese $iv0,$dat
aesmc $iv0,$iv0
vld1.32 {$dat},[$key2]
aese $iv0,$dat1
veor $iv0,$iv0,$dat
// The iv for second block
// $ivl- iv(low), $ivh - iv(high)
// the five ivs stored into, $iv0,$iv1,$iv2,$iv3,$iv4
fmov $ivl,$ivd00
fmov $ivh,$ivd01
mov $constnum,#0x87
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr#31
eor $ivl,$tmpmx,$ivl,lsl#1
fmov $ivd10,$ivl
fmov $ivd11,$ivh
ldr $rounds0,[$key1,#240] // next starting point
vld1.8 {$dat},[$inp],$step
vld1.32 {q8-q9},[$key1] // load key schedule...
sub $rounds0,$rounds0,#6
add $key_,$key1,$ivp,lsl#4 // pointer to last 7 round keys
sub $rounds0,$rounds0,#2
vld1.32 {q10-q11},[$key_],#32
vld1.32 {q12-q13},[$key_],#32
vld1.32 {q14-q15},[$key_],#32
vld1.32 {$rndlast},[$key_]
add $key_,$key1,#32
mov $rounds,$rounds0
// Encryption
.Lxts_enc:
vld1.8 {$dat2},[$inp],#16
subs $len,$len,#32 // bias
add $rounds,$rounds0,#2
vorr $in1,$dat,$dat
vorr $dat1,$dat,$dat
vorr $in3,$dat,$dat
vorr $in2,$dat2,$dat2
vorr $in4,$dat2,$dat2
b.lo .Lxts_inner_enc_tail
veor $dat,$dat,$iv0 // before encryption, xor with iv
veor $dat2,$dat2,$iv1
// The iv for third block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr#31
eor $ivl,$tmpmx,$ivl,lsl#1
fmov $ivd20,$ivl
fmov $ivd21,$ivh
vorr $dat1,$dat2,$dat2
vld1.8 {$dat2},[$inp],#16
vorr $in0,$dat,$dat
vorr $in1,$dat1,$dat1
veor $in2,$dat2,$iv2 // the third block
veor $dat2,$dat2,$iv2
cmp $len,#32
b.lo .Lxts_outer_enc_tail
// The iv for fourth block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr#31
eor $ivl,$tmpmx,$ivl,lsl#1
fmov $ivd30,$ivl
fmov $ivd31,$ivh
vld1.8 {$dat3},[$inp],#16
// The iv for fifth block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr#31
eor $ivl,$tmpmx,$ivl,lsl#1
fmov $ivd40,$ivl
fmov $ivd41,$ivh
vld1.8 {$dat4},[$inp],#16
veor $dat3,$dat3,$iv3 // the fourth block
veor $dat4,$dat4,$iv4
sub $len,$len,#32 // bias
mov $rounds,$rounds0
b .Loop5x_xts_enc
.align 4
.Loop5x_xts_enc:
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
aese $dat3,q8
aesmc $dat3,$dat3
aese $dat4,q8
aesmc $dat4,$dat4
vld1.32 {q8},[$key_],#16
subs $rounds,$rounds,#2
aese $dat0,q9
aesmc $dat0,$dat0
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
aese $dat3,q9
aesmc $dat3,$dat3
aese $dat4,q9
aesmc $dat4,$dat4
vld1.32 {q9},[$key_],#16
b.gt .Loop5x_xts_enc
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
aese $dat3,q8
aesmc $dat3,$dat3
aese $dat4,q8
aesmc $dat4,$dat4
subs $len,$len,#0x50 // because .Lxts_enc_tail4x
aese $dat0,q9
aesmc $dat0,$dat0
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
aese $dat3,q9
aesmc $dat3,$dat3
aese $dat4,q9
aesmc $dat4,$dat4
csel $xoffset,xzr,$len,gt // borrow x6, w6, "gt" is not typo
mov $key_,$key1
aese $dat0,q10
aesmc $dat0,$dat0
aese $dat1,q10
aesmc $dat1,$dat1
aese $dat2,q10
aesmc $dat2,$dat2
aese $dat3,q10
aesmc $dat3,$dat3
aese $dat4,q10
aesmc $dat4,$dat4
add $inp,$inp,$xoffset // x0 is adjusted in such way that
// at exit from the loop v1.16b-v26.16b
// are loaded with last "words"
add $xoffset,$len,#0x60 // because .Lxts_enc_tail4x
aese $dat0,q11
aesmc $dat0,$dat0
aese $dat1,q11
aesmc $dat1,$dat1
aese $dat2,q11
aesmc $dat2,$dat2
aese $dat3,q11
aesmc $dat3,$dat3
aese $dat4,q11
aesmc $dat4,$dat4
aese $dat0,q12
aesmc $dat0,$dat0
aese $dat1,q12
aesmc $dat1,$dat1
aese $dat2,q12
aesmc $dat2,$dat2
aese $dat3,q12
aesmc $dat3,$dat3
aese $dat4,q12
aesmc $dat4,$dat4
aese $dat0,q13
aesmc $dat0,$dat0
aese $dat1,q13
aesmc $dat1,$dat1
aese $dat2,q13
aesmc $dat2,$dat2
aese $dat3,q13
aesmc $dat3,$dat3
aese $dat4,q13
aesmc $dat4,$dat4
aese $dat0,q14
aesmc $dat0,$dat0
aese $dat1,q14
aesmc $dat1,$dat1
aese $dat2,q14
aesmc $dat2,$dat2
aese $dat3,q14
aesmc $dat3,$dat3
aese $dat4,q14
aesmc $dat4,$dat4
veor $tmp0,$rndlast,$iv0
aese $dat0,q15
// The iv for first block of one iteration
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr#31
eor $ivl,$tmpmx,$ivl,lsl#1
fmov $ivd00,$ivl
fmov $ivd01,$ivh
veor $tmp1,$rndlast,$iv1
vld1.8 {$in0},[$inp],#16
aese $dat1,q15
// The iv for second block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr#31
eor $ivl,$tmpmx,$ivl,lsl#1
fmov $ivd10,$ivl
fmov $ivd11,$ivh
veor $tmp2,$rndlast,$iv2
vld1.8 {$in1},[$inp],#16
aese $dat2,q15
// The iv for third block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr#31
eor $ivl,$tmpmx,$ivl,lsl#1
fmov $ivd20,$ivl
fmov $ivd21,$ivh
veor $tmp3,$rndlast,$iv3
vld1.8 {$in2},[$inp],#16
aese $dat3,q15
// The iv for fourth block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr#31
eor $ivl,$tmpmx,$ivl,lsl#1
fmov $ivd30,$ivl
fmov $ivd31,$ivh
veor $tmp4,$rndlast,$iv4
vld1.8 {$in3},[$inp],#16
aese $dat4,q15
// The iv for fifth block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd40,$ivl
fmov $ivd41,$ivh
vld1.8 {$in4},[$inp],#16
cbz $xoffset,.Lxts_enc_tail4x
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
veor $tmp0,$tmp0,$dat0
veor $dat0,$in0,$iv0
veor $tmp1,$tmp1,$dat1
veor $dat1,$in1,$iv1
veor $tmp2,$tmp2,$dat2
veor $dat2,$in2,$iv2
veor $tmp3,$tmp3,$dat3
veor $dat3,$in3,$iv3
veor $tmp4,$tmp4,$dat4
vst1.8 {$tmp0},[$out],#16
veor $dat4,$in4,$iv4
vst1.8 {$tmp1},[$out],#16
mov $rounds,$rounds0
vst1.8 {$tmp2},[$out],#16
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
vst1.8 {$tmp3},[$out],#16
vst1.8 {$tmp4},[$out],#16
b.hs .Loop5x_xts_enc
// If left 4 blocks, borrow the five block's processing.
cmn $len,#0x10
b.ne .Loop5x_enc_after
vorr $iv4,$iv3,$iv3
vorr $iv3,$iv2,$iv2
vorr $iv2,$iv1,$iv1
vorr $iv1,$iv0,$iv0
fmov $ivl,$ivd40
fmov $ivh,$ivd41
veor $dat0,$iv0,$in0
veor $dat1,$iv1,$in1
veor $dat2,$in2,$iv2
veor $dat3,$in3,$iv3
veor $dat4,$in4,$iv4
b.eq .Loop5x_xts_enc
.Loop5x_enc_after:
add $len,$len,#0x50
cbz $len,.Lxts_enc_done
add $rounds,$rounds0,#2
subs $len,$len,#0x30
b.lo .Lxts_inner_enc_tail
veor $dat0,$iv0,$in2
veor $dat1,$iv1,$in3
veor $dat2,$in4,$iv2
b .Lxts_outer_enc_tail
.align 4
.Lxts_enc_tail4x:
add $inp,$inp,#16
veor $tmp1,$dat1,$tmp1
vst1.8 {$tmp1},[$out],#16
veor $tmp2,$dat2,$tmp2
vst1.8 {$tmp2},[$out],#16
veor $tmp3,$dat3,$tmp3
veor $tmp4,$dat4,$tmp4
vst1.8 {$tmp3-$tmp4},[$out],#32
b .Lxts_enc_done
.align 4
.Lxts_outer_enc_tail:
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
vld1.32 {q8},[$key_],#16
subs $rounds,$rounds,#2
aese $dat0,q9
aesmc $dat0,$dat0
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
vld1.32 {q9},[$key_],#16
b.gt .Lxts_outer_enc_tail
aese $dat0,q8
aesmc $dat0,$dat0
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
veor $tmp0,$iv0,$rndlast
subs $len,$len,#0x30
// The iv for first block
fmov $ivl,$ivd20
fmov $ivh,$ivd21
//mov $constnum,#0x87
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr#31
eor $ivl,$tmpmx,$ivl,lsl#1
fmov $ivd00,$ivl
fmov $ivd01,$ivh
veor $tmp1,$iv1,$rndlast
csel $xoffset,$len,$xoffset,lo // x6, w6, is zero at this point
aese $dat0,q9
aesmc $dat0,$dat0
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
veor $tmp2,$iv2,$rndlast
add $xoffset,$xoffset,#0x20
add $inp,$inp,$xoffset
mov $key_,$key1
aese $dat0,q12
aesmc $dat0,$dat0
aese $dat1,q12
aesmc $dat1,$dat1
aese $dat2,q12
aesmc $dat2,$dat2
aese $dat0,q13
aesmc $dat0,$dat0
aese $dat1,q13
aesmc $dat1,$dat1
aese $dat2,q13
aesmc $dat2,$dat2
aese $dat0,q14
aesmc $dat0,$dat0
aese $dat1,q14
aesmc $dat1,$dat1
aese $dat2,q14
aesmc $dat2,$dat2
aese $dat0,q15
aese $dat1,q15
aese $dat2,q15
vld1.8 {$in2},[$inp],#16
add $rounds,$rounds0,#2
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
veor $tmp0,$tmp0,$dat0
veor $tmp1,$tmp1,$dat1
veor $dat2,$dat2,$tmp2
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
vst1.8 {$tmp0},[$out],#16
vst1.8 {$tmp1},[$out],#16
vst1.8 {$dat2},[$out],#16
cmn $len,#0x30
b.eq .Lxts_enc_done
.Lxts_encxor_one:
vorr $in3,$in1,$in1
vorr $in4,$in2,$in2
nop
.Lxts_inner_enc_tail:
cmn $len,#0x10
veor $dat1,$in3,$iv0
veor $dat2,$in4,$iv1
b.eq .Lxts_enc_tail_loop
veor $dat2,$in4,$iv0
.Lxts_enc_tail_loop:
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
vld1.32 {q8},[$key_],#16
subs $rounds,$rounds,#2
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
vld1.32 {q9},[$key_],#16
b.gt .Lxts_enc_tail_loop
aese $dat1,q8
aesmc $dat1,$dat1
aese $dat2,q8
aesmc $dat2,$dat2
aese $dat1,q9
aesmc $dat1,$dat1
aese $dat2,q9
aesmc $dat2,$dat2
aese $dat1,q12
aesmc $dat1,$dat1
aese $dat2,q12
aesmc $dat2,$dat2
cmn $len,#0x20
aese $dat1,q13
aesmc $dat1,$dat1
aese $dat2,q13
aesmc $dat2,$dat2
veor $tmp1,$iv0,$rndlast
aese $dat1,q14
aesmc $dat1,$dat1
aese $dat2,q14
aesmc $dat2,$dat2
veor $tmp2,$iv1,$rndlast
aese $dat1,q15
aese $dat2,q15
b.eq .Lxts_enc_one
veor $tmp1,$tmp1,$dat1
vst1.8 {$tmp1},[$out],#16
veor $tmp2,$tmp2,$dat2
vorr $iv0,$iv1,$iv1
vst1.8 {$tmp2},[$out],#16
fmov $ivl,$ivd10
fmov $ivh,$ivd11
mov $constnum,#0x87
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd00,$ivl
fmov $ivd01,$ivh
b .Lxts_enc_done
.Lxts_enc_one:
veor $tmp1,$tmp1,$dat2
vorr $iv0,$iv0,$iv0
vst1.8 {$tmp1},[$out],#16
fmov $ivl,$ivd00
fmov $ivh,$ivd01
mov $constnum,#0x87
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd00,$ivl
fmov $ivd01,$ivh
b .Lxts_enc_done
.align 5
.Lxts_enc_done:
// Process the tail block with cipher stealing.
tst $tailcnt,#0xf
b.eq .Lxts_abort
mov $tmpinp,$inp
mov $tmpoutp,$out
sub $out,$out,#16
.composite_enc_loop:
subs $tailcnt,$tailcnt,#1
ldrb $l2outp,[$out,$tailcnt]
ldrb $loutp,[$tmpinp,$tailcnt]
strb $l2outp,[$tmpoutp,$tailcnt]
strb $loutp,[$out,$tailcnt]
b.gt .composite_enc_loop
.Lxts_enc_load_done:
vld1.8 {$tmpin},[$out]
veor $tmpin,$tmpin,$iv0
// Encrypt the composite block to get the last second encrypted text block
ldr $rounds,[$key1,#240] // load key schedule...
- vld1.8 {$dat},[$key1],#16
+ vld1.32 {$dat},[$key1],#16
sub $rounds,$rounds,#2
- vld1.8 {$dat1},[$key1],#16 // load key schedule...
+ vld1.32 {$dat1},[$key1],#16 // load key schedule...
.Loop_final_enc:
aese $tmpin,$dat0
aesmc $tmpin,$tmpin
vld1.32 {$dat0},[$key1],#16
subs $rounds,$rounds,#2
aese $tmpin,$dat1
aesmc $tmpin,$tmpin
vld1.32 {$dat1},[$key1],#16
b.gt .Loop_final_enc
aese $tmpin,$dat0
aesmc $tmpin,$tmpin
vld1.32 {$dat0},[$key1]
aese $tmpin,$dat1
veor $tmpin,$tmpin,$dat0
veor $tmpin,$tmpin,$iv0
vst1.8 {$tmpin},[$out]
.Lxts_abort:
ldp $tailcnt,$midnumx,[sp,#48]
ldp $ivd10,$ivd20,[sp,#32]
ldp $ivd30,$ivd40,[sp,#16]
ldp $constnumx,$tmpinp,[sp],#64
.Lxts_enc_final_abort:
ret
.size ${prefix}_xts_encrypt,.-${prefix}_xts_encrypt
___
}}}
{{{
my ($inp,$out,$len,$key1,$key2,$ivp)=map("x$_",(0..5));
my ($rounds0,$rounds,$key_,$step,$ivl,$ivh)=("w5","w6","x7","x8","x9","x10");
my ($tmpoutp,$loutp,$l2outp,$tmpinp)=("x13","w14","w15","x20");
my ($tailcnt,$midnum,$midnumx,$constnum,$constnumx)=("x21","w22","x22","w19","x19");
my ($xoffset,$tmpmx,$tmpmw)=("x6","x11","w11");
my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$tmp2,$rndlast)=map("q$_",(0..7));
my ($iv0,$iv1,$iv2,$iv3,$iv4,$tmpin)=("v6.16b","v8.16b","v9.16b","v10.16b","v11.16b","v26.16b");
my ($ivd00,$ivd01,$ivd20,$ivd21)=("d6","v6.d[1]","d9","v9.d[1]");
my ($ivd10,$ivd11,$ivd30,$ivd31,$ivd40,$ivd41)=("d8","v8.d[1]","d10","v10.d[1]","d11","v11.d[1]");
my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1);
# q7 last round key
# q10-q15, q7 Last 7 round keys
# q8-q9 preloaded round keys except last 7 keys for big size
# q20, q21, q8-q9 preloaded round keys except last 7 keys for only 16 byte
{
my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
my ($dat3,$in3,$tmp3); # used only in 64-bit mode
my ($dat4,$in4,$tmp4);
if ($flavour =~ /64/) {
($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23));
}
$code.=<<___ if ($flavour =~ /64/);
.globl ${prefix}_xts_decrypt
.type ${prefix}_xts_decrypt,%function
.align 5
${prefix}_xts_decrypt:
___
$code.=<<___ if ($flavour =~ /64/);
cmp $len,#16
// Original input data size bigger than 16, jump to big size processing.
b.ne .Lxts_dec_big_size
// Encrypt the iv with key2, as the first XEX iv.
ldr $rounds,[$key2,#240]
- vld1.8 {$dat},[$key2],#16
+ vld1.32 {$dat},[$key2],#16
vld1.8 {$iv0},[$ivp]
sub $rounds,$rounds,#2
- vld1.8 {$dat1},[$key2],#16
+ vld1.32 {$dat1},[$key2],#16
.Loop_dec_small_iv_enc:
aese $iv0,$dat
aesmc $iv0,$iv0
vld1.32 {$dat},[$key2],#16
subs $rounds,$rounds,#2
aese $iv0,$dat1
aesmc $iv0,$iv0
vld1.32 {$dat1},[$key2],#16
b.gt .Loop_dec_small_iv_enc
aese $iv0,$dat
aesmc $iv0,$iv0
vld1.32 {$dat},[$key2]
aese $iv0,$dat1
veor $iv0,$iv0,$dat
vld1.8 {$dat0},[$inp]
veor $dat0,$iv0,$dat0
ldr $rounds,[$key1,#240]
vld1.32 {q20-q21},[$key1],#32 // load key schedule...
aesd $dat0,q20
aesimc $dat0,$dat0
vld1.32 {q8-q9},[$key1],#32 // load key schedule...
aesd $dat0,q21
aesimc $dat0,$dat0
subs $rounds,$rounds,#10 // bias
b.eq .Lxts_128_dec
.Lxts_dec_round_loop:
aesd $dat0,q8
aesimc $dat0,$dat0
vld1.32 {q8},[$key1],#16 // load key schedule...
aesd $dat0,q9
aesimc $dat0,$dat0
vld1.32 {q9},[$key1],#16 // load key schedule...
subs $rounds,$rounds,#2 // bias
b.gt .Lxts_dec_round_loop
.Lxts_128_dec:
vld1.32 {q10-q11},[$key1],#32 // load key schedule...
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat0,q9
aesimc $dat0,$dat0
vld1.32 {q12-q13},[$key1],#32 // load key schedule...
aesd $dat0,q10
aesimc $dat0,$dat0
aesd $dat0,q11
aesimc $dat0,$dat0
vld1.32 {q14-q15},[$key1],#32 // load key schedule...
aesd $dat0,q12
aesimc $dat0,$dat0
aesd $dat0,q13
aesimc $dat0,$dat0
vld1.32 {$rndlast},[$key1]
aesd $dat0,q14
aesimc $dat0,$dat0
aesd $dat0,q15
veor $dat0,$dat0,$rndlast
veor $dat0,$iv0,$dat0
vst1.8 {$dat0},[$out]
b .Lxts_dec_final_abort
.Lxts_dec_big_size:
___
$code.=<<___ if ($flavour =~ /64/);
stp $constnumx,$tmpinp,[sp,#-64]!
stp $tailcnt,$midnumx,[sp,#48]
stp $ivd10,$ivd20,[sp,#32]
stp $ivd30,$ivd40,[sp,#16]
and $tailcnt,$len,#0xf
and $len,$len,#-16
subs $len,$len,#16
mov $step,#16
b.lo .Lxts_dec_abort
// Encrypt the iv with key2, as the first XEX iv
ldr $rounds,[$key2,#240]
- vld1.8 {$dat},[$key2],#16
+ vld1.32 {$dat},[$key2],#16
vld1.8 {$iv0},[$ivp]
sub $rounds,$rounds,#2
- vld1.8 {$dat1},[$key2],#16
+ vld1.32 {$dat1},[$key2],#16
.Loop_dec_iv_enc:
aese $iv0,$dat
aesmc $iv0,$iv0
vld1.32 {$dat},[$key2],#16
subs $rounds,$rounds,#2
aese $iv0,$dat1
aesmc $iv0,$iv0
vld1.32 {$dat1},[$key2],#16
b.gt .Loop_dec_iv_enc
aese $iv0,$dat
aesmc $iv0,$iv0
vld1.32 {$dat},[$key2]
aese $iv0,$dat1
veor $iv0,$iv0,$dat
// The iv for second block
// $ivl- iv(low), $ivh - iv(high)
// the five ivs stored into, $iv0,$iv1,$iv2,$iv3,$iv4
fmov $ivl,$ivd00
fmov $ivh,$ivd01
mov $constnum,#0x87
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd10,$ivl
fmov $ivd11,$ivh
ldr $rounds0,[$key1,#240] // load rounds number
// The iv for third block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd20,$ivl
fmov $ivd21,$ivh
vld1.32 {q8-q9},[$key1] // load key schedule...
sub $rounds0,$rounds0,#6
add $key_,$key1,$ivp,lsl#4 // pointer to last 7 round keys
sub $rounds0,$rounds0,#2
vld1.32 {q10-q11},[$key_],#32 // load key schedule...
vld1.32 {q12-q13},[$key_],#32
vld1.32 {q14-q15},[$key_],#32
vld1.32 {$rndlast},[$key_]
// The iv for fourth block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd30,$ivl
fmov $ivd31,$ivh
add $key_,$key1,#32
mov $rounds,$rounds0
b .Lxts_dec
// Decryption
.align 5
.Lxts_dec:
tst $tailcnt,#0xf
b.eq .Lxts_dec_begin
subs $len,$len,#16
csel $step,xzr,$step,eq
vld1.8 {$dat},[$inp],#16
b.lo .Lxts_done
sub $inp,$inp,#16
.Lxts_dec_begin:
vld1.8 {$dat},[$inp],$step
subs $len,$len,#32 // bias
add $rounds,$rounds0,#2
vorr $in1,$dat,$dat
vorr $dat1,$dat,$dat
vorr $in3,$dat,$dat
vld1.8 {$dat2},[$inp],#16
vorr $in2,$dat2,$dat2
vorr $in4,$dat2,$dat2
b.lo .Lxts_inner_dec_tail
veor $dat,$dat,$iv0 // before decryt, xor with iv
veor $dat2,$dat2,$iv1
vorr $dat1,$dat2,$dat2
vld1.8 {$dat2},[$inp],#16
vorr $in0,$dat,$dat
vorr $in1,$dat1,$dat1
veor $in2,$dat2,$iv2 // third block xox with third iv
veor $dat2,$dat2,$iv2
cmp $len,#32
b.lo .Lxts_outer_dec_tail
vld1.8 {$dat3},[$inp],#16
// The iv for fifth block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd40,$ivl
fmov $ivd41,$ivh
vld1.8 {$dat4},[$inp],#16
veor $dat3,$dat3,$iv3 // the fourth block
veor $dat4,$dat4,$iv4
sub $len,$len,#32 // bias
mov $rounds,$rounds0
b .Loop5x_xts_dec
.align 4
.Loop5x_xts_dec:
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
aesd $dat3,q8
aesimc $dat3,$dat3
aesd $dat4,q8
aesimc $dat4,$dat4
vld1.32 {q8},[$key_],#16 // load key schedule...
subs $rounds,$rounds,#2
aesd $dat0,q9
aesimc $dat0,$dat0
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
aesd $dat3,q9
aesimc $dat3,$dat3
aesd $dat4,q9
aesimc $dat4,$dat4
vld1.32 {q9},[$key_],#16 // load key schedule...
b.gt .Loop5x_xts_dec
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
aesd $dat3,q8
aesimc $dat3,$dat3
aesd $dat4,q8
aesimc $dat4,$dat4
subs $len,$len,#0x50 // because .Lxts_dec_tail4x
aesd $dat0,q9
aesimc $dat0,$dat
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
aesd $dat3,q9
aesimc $dat3,$dat3
aesd $dat4,q9
aesimc $dat4,$dat4
csel $xoffset,xzr,$len,gt // borrow x6, w6, "gt" is not typo
mov $key_,$key1
aesd $dat0,q10
aesimc $dat0,$dat0
aesd $dat1,q10
aesimc $dat1,$dat1
aesd $dat2,q10
aesimc $dat2,$dat2
aesd $dat3,q10
aesimc $dat3,$dat3
aesd $dat4,q10
aesimc $dat4,$dat4
add $inp,$inp,$xoffset // x0 is adjusted in such way that
// at exit from the loop v1.16b-v26.16b
// are loaded with last "words"
add $xoffset,$len,#0x60 // because .Lxts_dec_tail4x
aesd $dat0,q11
aesimc $dat0,$dat0
aesd $dat1,q11
aesimc $dat1,$dat1
aesd $dat2,q11
aesimc $dat2,$dat2
aesd $dat3,q11
aesimc $dat3,$dat3
aesd $dat4,q11
aesimc $dat4,$dat4
aesd $dat0,q12
aesimc $dat0,$dat0
aesd $dat1,q12
aesimc $dat1,$dat1
aesd $dat2,q12
aesimc $dat2,$dat2
aesd $dat3,q12
aesimc $dat3,$dat3
aesd $dat4,q12
aesimc $dat4,$dat4
aesd $dat0,q13
aesimc $dat0,$dat0
aesd $dat1,q13
aesimc $dat1,$dat1
aesd $dat2,q13
aesimc $dat2,$dat2
aesd $dat3,q13
aesimc $dat3,$dat3
aesd $dat4,q13
aesimc $dat4,$dat4
aesd $dat0,q14
aesimc $dat0,$dat0
aesd $dat1,q14
aesimc $dat1,$dat1
aesd $dat2,q14
aesimc $dat2,$dat2
aesd $dat3,q14
aesimc $dat3,$dat3
aesd $dat4,q14
aesimc $dat4,$dat4
veor $tmp0,$rndlast,$iv0
aesd $dat0,q15
// The iv for first block of next iteration.
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd00,$ivl
fmov $ivd01,$ivh
veor $tmp1,$rndlast,$iv1
vld1.8 {$in0},[$inp],#16
aesd $dat1,q15
// The iv for second block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd10,$ivl
fmov $ivd11,$ivh
veor $tmp2,$rndlast,$iv2
vld1.8 {$in1},[$inp],#16
aesd $dat2,q15
// The iv for third block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd20,$ivl
fmov $ivd21,$ivh
veor $tmp3,$rndlast,$iv3
vld1.8 {$in2},[$inp],#16
aesd $dat3,q15
// The iv for fourth block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd30,$ivl
fmov $ivd31,$ivh
veor $tmp4,$rndlast,$iv4
vld1.8 {$in3},[$inp],#16
aesd $dat4,q15
// The iv for fifth block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd40,$ivl
fmov $ivd41,$ivh
vld1.8 {$in4},[$inp],#16
cbz $xoffset,.Lxts_dec_tail4x
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
veor $tmp0,$tmp0,$dat0
veor $dat0,$in0,$iv0
veor $tmp1,$tmp1,$dat1
veor $dat1,$in1,$iv1
veor $tmp2,$tmp2,$dat2
veor $dat2,$in2,$iv2
veor $tmp3,$tmp3,$dat3
veor $dat3,$in3,$iv3
veor $tmp4,$tmp4,$dat4
vst1.8 {$tmp0},[$out],#16
veor $dat4,$in4,$iv4
vst1.8 {$tmp1},[$out],#16
mov $rounds,$rounds0
vst1.8 {$tmp2},[$out],#16
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
vst1.8 {$tmp3},[$out],#16
vst1.8 {$tmp4},[$out],#16
b.hs .Loop5x_xts_dec
cmn $len,#0x10
b.ne .Loop5x_dec_after
// If x2($len) equal to -0x10, the left blocks is 4.
// After specially processing, utilize the five blocks processing again.
// It will use the following IVs: $iv0,$iv0,$iv1,$iv2,$iv3.
vorr $iv4,$iv3,$iv3
vorr $iv3,$iv2,$iv2
vorr $iv2,$iv1,$iv1
vorr $iv1,$iv0,$iv0
fmov $ivl,$ivd40
fmov $ivh,$ivd41
veor $dat0,$iv0,$in0
veor $dat1,$iv1,$in1
veor $dat2,$in2,$iv2
veor $dat3,$in3,$iv3
veor $dat4,$in4,$iv4
b.eq .Loop5x_xts_dec
.Loop5x_dec_after:
add $len,$len,#0x50
cbz $len,.Lxts_done
add $rounds,$rounds0,#2
subs $len,$len,#0x30
b.lo .Lxts_inner_dec_tail
veor $dat0,$iv0,$in2
veor $dat1,$iv1,$in3
veor $dat2,$in4,$iv2
b .Lxts_outer_dec_tail
.align 4
.Lxts_dec_tail4x:
add $inp,$inp,#16
- vld1.32 {$dat0},[$inp],#16
+ tst $tailcnt,#0xf
veor $tmp1,$dat1,$tmp0
vst1.8 {$tmp1},[$out],#16
veor $tmp2,$dat2,$tmp2
vst1.8 {$tmp2},[$out],#16
veor $tmp3,$dat3,$tmp3
veor $tmp4,$dat4,$tmp4
vst1.8 {$tmp3-$tmp4},[$out],#32
+ b.eq .Lxts_dec_abort
+ vld1.8 {$dat0},[$inp],#16
b .Lxts_done
.align 4
.Lxts_outer_dec_tail:
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
vld1.32 {q8},[$key_],#16
subs $rounds,$rounds,#2
aesd $dat0,q9
aesimc $dat0,$dat0
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
vld1.32 {q9},[$key_],#16
b.gt .Lxts_outer_dec_tail
aesd $dat0,q8
aesimc $dat0,$dat0
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
veor $tmp0,$iv0,$rndlast
subs $len,$len,#0x30
// The iv for first block
fmov $ivl,$ivd20
fmov $ivh,$ivd21
mov $constnum,#0x87
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd00,$ivl
fmov $ivd01,$ivh
veor $tmp1,$iv1,$rndlast
csel $xoffset,$len,$xoffset,lo // x6, w6, is zero at this point
aesd $dat0,q9
aesimc $dat0,$dat0
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
veor $tmp2,$iv2,$rndlast
// The iv for second block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd10,$ivl
fmov $ivd11,$ivh
add $xoffset,$xoffset,#0x20
add $inp,$inp,$xoffset // $inp is adjusted to the last data
mov $key_,$key1
// The iv for third block
extr $midnumx,$ivh,$ivh,#32
extr $ivh,$ivh,$ivl,#63
and $tmpmw,$constnum,$midnum,asr #31
eor $ivl,$tmpmx,$ivl,lsl #1
fmov $ivd20,$ivl
fmov $ivd21,$ivh
aesd $dat0,q12
aesimc $dat0,$dat0
aesd $dat1,q12
aesimc $dat1,$dat1
aesd $dat2,q12
aesimc $dat2,$dat2
aesd $dat0,q13
aesimc $dat0,$dat0
aesd $dat1,q13
aesimc $dat1,$dat1
aesd $dat2,q13
aesimc $dat2,$dat2
aesd $dat0,q14
aesimc $dat0,$dat0
aesd $dat1,q14
aesimc $dat1,$dat1
aesd $dat2,q14
aesimc $dat2,$dat2
vld1.8 {$in2},[$inp],#16
aesd $dat0,q15
aesd $dat1,q15
aesd $dat2,q15
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
add $rounds,$rounds0,#2
veor $tmp0,$tmp0,$dat0
veor $tmp1,$tmp1,$dat1
veor $dat2,$dat2,$tmp2
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
vst1.8 {$tmp0},[$out],#16
vst1.8 {$tmp1},[$out],#16
vst1.8 {$dat2},[$out],#16
cmn $len,#0x30
add $len,$len,#0x30
b.eq .Lxts_done
sub $len,$len,#0x30
vorr $in3,$in1,$in1
vorr $in4,$in2,$in2
nop
.Lxts_inner_dec_tail:
// $len == -0x10 means two blocks left.
cmn $len,#0x10
veor $dat1,$in3,$iv0
veor $dat2,$in4,$iv1
b.eq .Lxts_dec_tail_loop
veor $dat2,$in4,$iv0
.Lxts_dec_tail_loop:
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
vld1.32 {q8},[$key_],#16
subs $rounds,$rounds,#2
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
vld1.32 {q9},[$key_],#16
b.gt .Lxts_dec_tail_loop
aesd $dat1,q8
aesimc $dat1,$dat1
aesd $dat2,q8
aesimc $dat2,$dat2
aesd $dat1,q9
aesimc $dat1,$dat1
aesd $dat2,q9
aesimc $dat2,$dat2
aesd $dat1,q12
aesimc $dat1,$dat1
aesd $dat2,q12
aesimc $dat2,$dat2
cmn $len,#0x20
aesd $dat1,q13
aesimc $dat1,$dat1
aesd $dat2,q13
aesimc $dat2,$dat2
veor $tmp1,$iv0,$rndlast
aesd $dat1,q14
aesimc $dat1,$dat1
aesd $dat2,q14
aesimc $dat2,$dat2
veor $tmp2,$iv1,$rndlast
aesd $dat1,q15
aesd $dat2,q15
b.eq .Lxts_dec_one
veor $tmp1,$tmp1,$dat1
veor $tmp2,$tmp2,$dat2
vorr $iv0,$iv2,$iv2
vorr $iv1,$iv3,$iv3
vst1.8 {$tmp1},[$out],#16
vst1.8 {$tmp2},[$out],#16
add $len,$len,#16
b .Lxts_done
.Lxts_dec_one:
veor $tmp1,$tmp1,$dat2
vorr $iv0,$iv1,$iv1
vorr $iv1,$iv2,$iv2
vst1.8 {$tmp1},[$out],#16
add $len,$len,#32
.Lxts_done:
tst $tailcnt,#0xf
b.eq .Lxts_dec_abort
// Processing the last two blocks with cipher stealing.
mov x7,x3
cbnz x2,.Lxts_dec_1st_done
- vld1.32 {$dat0},[$inp],#16
+ vld1.8 {$dat0},[$inp],#16
// Decrypt the last secod block to get the last plain text block
.Lxts_dec_1st_done:
eor $tmpin,$dat0,$iv1
ldr $rounds,[$key1,#240]
vld1.32 {$dat0},[$key1],#16
sub $rounds,$rounds,#2
vld1.32 {$dat1},[$key1],#16
.Loop_final_2nd_dec:
aesd $tmpin,$dat0
aesimc $tmpin,$tmpin
vld1.32 {$dat0},[$key1],#16 // load key schedule...
subs $rounds,$rounds,#2
aesd $tmpin,$dat1
aesimc $tmpin,$tmpin
vld1.32 {$dat1},[$key1],#16 // load key schedule...
b.gt .Loop_final_2nd_dec
aesd $tmpin,$dat0
aesimc $tmpin,$tmpin
vld1.32 {$dat0},[$key1]
aesd $tmpin,$dat1
veor $tmpin,$tmpin,$dat0
veor $tmpin,$tmpin,$iv1
vst1.8 {$tmpin},[$out]
mov $tmpinp,$inp
add $tmpoutp,$out,#16
// Composite the tailcnt "16 byte not aligned block" into the last second plain blocks
// to get the last encrypted block.
.composite_dec_loop:
subs $tailcnt,$tailcnt,#1
ldrb $l2outp,[$out,$tailcnt]
ldrb $loutp,[$tmpinp,$tailcnt]
strb $l2outp,[$tmpoutp,$tailcnt]
strb $loutp,[$out,$tailcnt]
b.gt .composite_dec_loop
.Lxts_dec_load_done:
vld1.8 {$tmpin},[$out]
veor $tmpin,$tmpin,$iv0
// Decrypt the composite block to get the last second plain text block
ldr $rounds,[$key_,#240]
- vld1.8 {$dat},[$key_],#16
+ vld1.32 {$dat},[$key_],#16
sub $rounds,$rounds,#2
- vld1.8 {$dat1},[$key_],#16
+ vld1.32 {$dat1},[$key_],#16
.Loop_final_dec:
aesd $tmpin,$dat0
aesimc $tmpin,$tmpin
vld1.32 {$dat0},[$key_],#16 // load key schedule...
subs $rounds,$rounds,#2
aesd $tmpin,$dat1
aesimc $tmpin,$tmpin
vld1.32 {$dat1},[$key_],#16 // load key schedule...
b.gt .Loop_final_dec
aesd $tmpin,$dat0
aesimc $tmpin,$tmpin
vld1.32 {$dat0},[$key_]
aesd $tmpin,$dat1
veor $tmpin,$tmpin,$dat0
veor $tmpin,$tmpin,$iv0
vst1.8 {$tmpin},[$out]
.Lxts_dec_abort:
ldp $tailcnt,$midnumx,[sp,#48]
ldp $ivd10,$ivd20,[sp,#32]
ldp $ivd30,$ivd40,[sp,#16]
ldp $constnumx,$tmpinp,[sp],#64
.Lxts_dec_final_abort:
ret
.size ${prefix}_xts_decrypt,.-${prefix}_xts_decrypt
___
}
}}}
$code.=<<___;
#endif
___
########################################
if ($flavour =~ /64/) { ######## 64-bit code
my %opcode = (
"aesd" => 0x4e285800, "aese" => 0x4e284800,
"aesimc"=> 0x4e287800, "aesmc" => 0x4e286800 );
local *unaes = sub {
my ($mnemonic,$arg)=@_;
$arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)/o &&
sprintf ".inst\t0x%08x\t//%s %s",
$opcode{$mnemonic}|$1|($2<<5),
$mnemonic,$arg;
};
foreach(split("\n",$code)) {
s/\`([^\`]*)\`/eval($1)/geo;
s/\bq([0-9]+)\b/"v".($1<8?$1:$1+8).".16b"/geo; # old->new registers
s/@\s/\/\//o; # old->new style commentary
#s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or
s/cclr\s+([wx])([^,]+),\s*([a-z]+)/csel $1$2,$1zr,$1$2,$3/o or
s/mov\.([a-z]+)\s+([wx][0-9]+),\s*([wx][0-9]+)/csel $2,$3,$2,$1/o or
s/vmov\.i8/movi/o or # fix up legacy mnemonics
s/vext\.8/ext/o or
s/vrev32\.8/rev32/o or
s/vtst\.8/cmtst/o or
s/vshr/ushr/o or
s/^(\s+)v/$1/o or # strip off v prefix
s/\bbx\s+lr\b/ret/o;
# fix up remaining legacy suffixes
s/\.[ui]?8//o;
m/\],#8/o and s/\.16b/\.8b/go;
s/\.[ui]?32//o and s/\.16b/\.4s/go;
s/\.[ui]?64//o and s/\.16b/\.2d/go;
s/\.[42]([sd])\[([0-3])\]/\.$1\[$2\]/o;
print $_,"\n";
}
} else { ######## 32-bit code
my %opcode = (
"aesd" => 0xf3b00340, "aese" => 0xf3b00300,
"aesimc"=> 0xf3b003c0, "aesmc" => 0xf3b00380 );
local *unaes = sub {
my ($mnemonic,$arg)=@_;
if ($arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)/o) {
my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19)
|(($2&7)<<1) |(($2&8)<<2);
# since ARMv7 instructions are always encoded little-endian.
# correct solution is to use .inst directive, but older
# assemblers don't implement it:-(
sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s",
$word&0xff,($word>>8)&0xff,
($word>>16)&0xff,($word>>24)&0xff,
$mnemonic,$arg;
}
};
sub unvtbl {
my $arg=shift;
$arg =~ m/q([0-9]+),\s*\{q([0-9]+)\},\s*q([0-9]+)/o &&
sprintf "vtbl.8 d%d,{q%d},d%d\n\t".
"vtbl.8 d%d,{q%d},d%d", 2*$1,$2,2*$3, 2*$1+1,$2,2*$3+1;
}
sub unvdup32 {
my $arg=shift;
$arg =~ m/q([0-9]+),\s*q([0-9]+)\[([0-3])\]/o &&
sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1;
}
sub unvmov32 {
my $arg=shift;
$arg =~ m/q([0-9]+)\[([0-3])\],(.*)/o &&
sprintf "vmov.32 d%d[%d],%s",2*$1+($2>>1),$2&1,$3;
}
foreach(split("\n",$code)) {
s/\`([^\`]*)\`/eval($1)/geo;
s/\b[wx]([0-9]+)\b/r$1/go; # new->old registers
s/\bv([0-9])\.[12468]+[bsd]\b/q$1/go; # new->old registers
s/\/\/\s?/@ /o; # new->old style commentary
# fix up remaining new-style suffixes
s/\{q([0-9]+)\},\s*\[(.+)\],#8/sprintf "{d%d},[$2]!",2*$1/eo or
s/\],#[0-9]+/]!/o;
s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or
s/cclr\s+([^,]+),\s*([a-z]+)/mov.$2 $1,#0/o or
s/vtbl\.8\s+(.*)/unvtbl($1)/geo or
s/vdup\.32\s+(.*)/unvdup32($1)/geo or
s/vmov\.32\s+(.*)/unvmov32($1)/geo or
s/^(\s+)b\./$1b/o or
s/^(\s+)ret/$1bx\tlr/o;
if (s/^(\s+)mov\.([a-z]+)/$1mov$2/) {
print " it $2\n";
}
print $_,"\n";
}
}
close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/aes/asm/bsaes-armv7.pl b/crypto/aes/asm/bsaes-armv7.pl
index 9c5dd5839acb..6cbd00e2c672 100644
--- a/crypto/aes/asm/bsaes-armv7.pl
+++ b/crypto/aes/asm/bsaes-armv7.pl
@@ -1,2494 +1,2494 @@
#! /usr/bin/env perl
-# Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2012-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
# ====================================================================
# 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/.
#
# Specific modes and adaptation for Linux kernel by Ard Biesheuvel
-# of Linaro. Permission to use under GPL terms is granted.
+# of Linaro.
# ====================================================================
# Bit-sliced AES for ARM NEON
#
# February 2012.
#
# This implementation is direct adaptation of bsaes-x86_64 module for
# ARM NEON. Except that this module is endian-neutral [in sense that
# it can be compiled for either endianness] by courtesy of vld1.8's
# neutrality. Initial version doesn't implement interface to OpenSSL,
# only low-level primitives and unsupported entry points, just enough
# to collect performance results, which for Cortex-A8 core are:
#
# encrypt 19.5 cycles per byte processed with 128-bit key
# decrypt 22.1 cycles per byte processed with 128-bit key
# key conv. 440 cycles per 128-bit key/0.18 of 8x block
#
# Snapdragon S4 encrypts byte in 17.6 cycles and decrypts in 19.7,
# which is [much] worse than anticipated (for further details see
# http://www.openssl.org/~appro/Snapdragon-S4.html).
#
# Cortex-A15 manages in 14.2/16.1 cycles [when integer-only code
# manages in 20.0 cycles].
#
# When comparing to x86_64 results keep in mind that NEON unit is
# [mostly] single-issue and thus can't [fully] benefit from
# instruction-level parallelism. And when comparing to aes-armv4
# results keep in mind key schedule conversion overhead (see
# bsaes-x86_64.pl for further details)...
#
# <appro@openssl.org>
# April-August 2013
# Add CBC, CTR and XTS subroutines and adapt for kernel use; courtesy of Ard.
# $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
$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
if ($flavour && $flavour ne "void") {
$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 STDOUT,"| \"$^X\" $xlate $flavour \"$output\""
or die "can't call $xlate: $!";
} else {
$output and open STDOUT,">$output";
}
my ($inp,$out,$len,$key)=("r0","r1","r2","r3");
my @XMM=map("q$_",(0..15));
{
my ($key,$rounds,$const)=("r4","r5","r6");
sub Dlo() { shift=~m|q([1]?[0-9])|?"d".($1*2):""; }
sub Dhi() { shift=~m|q([1]?[0-9])|?"d".($1*2+1):""; }
sub Sbox {
# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
# output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb
my @b=@_[0..7];
my @t=@_[8..11];
my @s=@_[12..15];
&InBasisChange (@b);
&Inv_GF256 (@b[6,5,0,3,7,1,4,2],@t,@s);
&OutBasisChange (@b[7,1,4,2,6,5,0,3]);
}
sub InBasisChange {
# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
my @b=@_[0..7];
$code.=<<___;
veor @b[2], @b[2], @b[1]
veor @b[5], @b[5], @b[6]
veor @b[3], @b[3], @b[0]
veor @b[6], @b[6], @b[2]
veor @b[5], @b[5], @b[0]
veor @b[6], @b[6], @b[3]
veor @b[3], @b[3], @b[7]
veor @b[7], @b[7], @b[5]
veor @b[3], @b[3], @b[4]
veor @b[4], @b[4], @b[5]
veor @b[2], @b[2], @b[7]
veor @b[3], @b[3], @b[1]
veor @b[1], @b[1], @b[5]
___
}
sub OutBasisChange {
# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
# output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb
my @b=@_[0..7];
$code.=<<___;
veor @b[0], @b[0], @b[6]
veor @b[1], @b[1], @b[4]
veor @b[4], @b[4], @b[6]
veor @b[2], @b[2], @b[0]
veor @b[6], @b[6], @b[1]
veor @b[1], @b[1], @b[5]
veor @b[5], @b[5], @b[3]
veor @b[3], @b[3], @b[7]
veor @b[7], @b[7], @b[5]
veor @b[2], @b[2], @b[5]
veor @b[4], @b[4], @b[7]
___
}
sub InvSbox {
# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
# output in lsb > [b0, b1, b6, b4, b2, b7, b3, b5] < msb
my @b=@_[0..7];
my @t=@_[8..11];
my @s=@_[12..15];
&InvInBasisChange (@b);
&Inv_GF256 (@b[5,1,2,6,3,7,0,4],@t,@s);
&InvOutBasisChange (@b[3,7,0,4,5,1,2,6]);
}
sub InvInBasisChange { # OutBasisChange in reverse (with twist)
my @b=@_[5,1,2,6,3,7,0,4];
$code.=<<___
veor @b[1], @b[1], @b[7]
veor @b[4], @b[4], @b[7]
veor @b[7], @b[7], @b[5]
veor @b[1], @b[1], @b[3]
veor @b[2], @b[2], @b[5]
veor @b[3], @b[3], @b[7]
veor @b[6], @b[6], @b[1]
veor @b[2], @b[2], @b[0]
veor @b[5], @b[5], @b[3]
veor @b[4], @b[4], @b[6]
veor @b[0], @b[0], @b[6]
veor @b[1], @b[1], @b[4]
___
}
sub InvOutBasisChange { # InBasisChange in reverse
my @b=@_[2,5,7,3,6,1,0,4];
$code.=<<___;
veor @b[1], @b[1], @b[5]
veor @b[2], @b[2], @b[7]
veor @b[3], @b[3], @b[1]
veor @b[4], @b[4], @b[5]
veor @b[7], @b[7], @b[5]
veor @b[3], @b[3], @b[4]
veor @b[5], @b[5], @b[0]
veor @b[3], @b[3], @b[7]
veor @b[6], @b[6], @b[2]
veor @b[2], @b[2], @b[1]
veor @b[6], @b[6], @b[3]
veor @b[3], @b[3], @b[0]
veor @b[5], @b[5], @b[6]
___
}
sub Mul_GF4 {
#;*************************************************************
#;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) *
#;*************************************************************
my ($x0,$x1,$y0,$y1,$t0,$t1)=@_;
$code.=<<___;
veor $t0, $y0, $y1
vand $t0, $t0, $x0
veor $x0, $x0, $x1
vand $t1, $x1, $y0
vand $x0, $x0, $y1
veor $x1, $t1, $t0
veor $x0, $x0, $t1
___
}
sub Mul_GF4_N { # not used, see next subroutine
# multiply and scale by N
my ($x0,$x1,$y0,$y1,$t0)=@_;
$code.=<<___;
veor $t0, $y0, $y1
vand $t0, $t0, $x0
veor $x0, $x0, $x1
vand $x1, $x1, $y0
vand $x0, $x0, $y1
veor $x1, $x1, $x0
veor $x0, $x0, $t0
___
}
sub Mul_GF4_N_GF4 {
# interleaved Mul_GF4_N and Mul_GF4
my ($x0,$x1,$y0,$y1,$t0,
$x2,$x3,$y2,$y3,$t1)=@_;
$code.=<<___;
veor $t0, $y0, $y1
veor $t1, $y2, $y3
vand $t0, $t0, $x0
vand $t1, $t1, $x2
veor $x0, $x0, $x1
veor $x2, $x2, $x3
vand $x1, $x1, $y0
vand $x3, $x3, $y2
vand $x0, $x0, $y1
vand $x2, $x2, $y3
veor $x1, $x1, $x0
veor $x2, $x2, $x3
veor $x0, $x0, $t0
veor $x3, $x3, $t1
___
}
sub Mul_GF16_2 {
my @x=@_[0..7];
my @y=@_[8..11];
my @t=@_[12..15];
$code.=<<___;
veor @t[0], @x[0], @x[2]
veor @t[1], @x[1], @x[3]
___
&Mul_GF4 (@x[0], @x[1], @y[0], @y[1], @t[2..3]);
$code.=<<___;
veor @y[0], @y[0], @y[2]
veor @y[1], @y[1], @y[3]
___
Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3],
@x[2], @x[3], @y[2], @y[3], @t[2]);
$code.=<<___;
veor @x[0], @x[0], @t[0]
veor @x[2], @x[2], @t[0]
veor @x[1], @x[1], @t[1]
veor @x[3], @x[3], @t[1]
veor @t[0], @x[4], @x[6]
veor @t[1], @x[5], @x[7]
___
&Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3],
@x[6], @x[7], @y[2], @y[3], @t[2]);
$code.=<<___;
veor @y[0], @y[0], @y[2]
veor @y[1], @y[1], @y[3]
___
&Mul_GF4 (@x[4], @x[5], @y[0], @y[1], @t[2..3]);
$code.=<<___;
veor @x[4], @x[4], @t[0]
veor @x[6], @x[6], @t[0]
veor @x[5], @x[5], @t[1]
veor @x[7], @x[7], @t[1]
___
}
sub Inv_GF256 {
#;********************************************************************
#;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144) *
#;********************************************************************
my @x=@_[0..7];
my @t=@_[8..11];
my @s=@_[12..15];
# direct optimizations from hardware
$code.=<<___;
veor @t[3], @x[4], @x[6]
veor @t[2], @x[5], @x[7]
veor @t[1], @x[1], @x[3]
veor @s[1], @x[7], @x[6]
vmov @t[0], @t[2]
veor @s[0], @x[0], @x[2]
vorr @t[2], @t[2], @t[1]
veor @s[3], @t[3], @t[0]
vand @s[2], @t[3], @s[0]
vorr @t[3], @t[3], @s[0]
veor @s[0], @s[0], @t[1]
vand @t[0], @t[0], @t[1]
veor @t[1], @x[3], @x[2]
vand @s[3], @s[3], @s[0]
vand @s[1], @s[1], @t[1]
veor @t[1], @x[4], @x[5]
veor @s[0], @x[1], @x[0]
veor @t[3], @t[3], @s[1]
veor @t[2], @t[2], @s[1]
vand @s[1], @t[1], @s[0]
vorr @t[1], @t[1], @s[0]
veor @t[3], @t[3], @s[3]
veor @t[0], @t[0], @s[1]
veor @t[2], @t[2], @s[2]
veor @t[1], @t[1], @s[3]
veor @t[0], @t[0], @s[2]
vand @s[0], @x[7], @x[3]
veor @t[1], @t[1], @s[2]
vand @s[1], @x[6], @x[2]
vand @s[2], @x[5], @x[1]
vorr @s[3], @x[4], @x[0]
veor @t[3], @t[3], @s[0]
veor @t[1], @t[1], @s[2]
veor @t[0], @t[0], @s[3]
veor @t[2], @t[2], @s[1]
@ Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
@ new smaller inversion
vand @s[2], @t[3], @t[1]
vmov @s[0], @t[0]
veor @s[1], @t[2], @s[2]
veor @s[3], @t[0], @s[2]
veor @s[2], @t[0], @s[2] @ @s[2]=@s[3]
vbsl @s[1], @t[1], @t[0]
vbsl @s[3], @t[3], @t[2]
veor @t[3], @t[3], @t[2]
vbsl @s[0], @s[1], @s[2]
vbsl @t[0], @s[2], @s[1]
vand @s[2], @s[0], @s[3]
veor @t[1], @t[1], @t[0]
veor @s[2], @s[2], @t[3]
___
# output in s3, s2, s1, t1
# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3
# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3
&Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]);
### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb
}
# AES linear components
sub ShiftRows {
my @x=@_[0..7];
my @t=@_[8..11];
my $mask=pop;
$code.=<<___;
vldmia $key!, {@t[0]-@t[3]}
veor @t[0], @t[0], @x[0]
veor @t[1], @t[1], @x[1]
vtbl.8 `&Dlo(@x[0])`, {@t[0]}, `&Dlo($mask)`
vtbl.8 `&Dhi(@x[0])`, {@t[0]}, `&Dhi($mask)`
vldmia $key!, {@t[0]}
veor @t[2], @t[2], @x[2]
vtbl.8 `&Dlo(@x[1])`, {@t[1]}, `&Dlo($mask)`
vtbl.8 `&Dhi(@x[1])`, {@t[1]}, `&Dhi($mask)`
vldmia $key!, {@t[1]}
veor @t[3], @t[3], @x[3]
vtbl.8 `&Dlo(@x[2])`, {@t[2]}, `&Dlo($mask)`
vtbl.8 `&Dhi(@x[2])`, {@t[2]}, `&Dhi($mask)`
vldmia $key!, {@t[2]}
vtbl.8 `&Dlo(@x[3])`, {@t[3]}, `&Dlo($mask)`
vtbl.8 `&Dhi(@x[3])`, {@t[3]}, `&Dhi($mask)`
vldmia $key!, {@t[3]}
veor @t[0], @t[0], @x[4]
veor @t[1], @t[1], @x[5]
vtbl.8 `&Dlo(@x[4])`, {@t[0]}, `&Dlo($mask)`
vtbl.8 `&Dhi(@x[4])`, {@t[0]}, `&Dhi($mask)`
veor @t[2], @t[2], @x[6]
vtbl.8 `&Dlo(@x[5])`, {@t[1]}, `&Dlo($mask)`
vtbl.8 `&Dhi(@x[5])`, {@t[1]}, `&Dhi($mask)`
veor @t[3], @t[3], @x[7]
vtbl.8 `&Dlo(@x[6])`, {@t[2]}, `&Dlo($mask)`
vtbl.8 `&Dhi(@x[6])`, {@t[2]}, `&Dhi($mask)`
vtbl.8 `&Dlo(@x[7])`, {@t[3]}, `&Dlo($mask)`
vtbl.8 `&Dhi(@x[7])`, {@t[3]}, `&Dhi($mask)`
___
}
sub MixColumns {
# modified to emit output in order suitable for feeding back to aesenc[last]
my @x=@_[0..7];
my @t=@_[8..15];
my $inv=@_[16]; # optional
$code.=<<___;
vext.8 @t[0], @x[0], @x[0], #12 @ x0 <<< 32
vext.8 @t[1], @x[1], @x[1], #12
veor @x[0], @x[0], @t[0] @ x0 ^ (x0 <<< 32)
vext.8 @t[2], @x[2], @x[2], #12
veor @x[1], @x[1], @t[1]
vext.8 @t[3], @x[3], @x[3], #12
veor @x[2], @x[2], @t[2]
vext.8 @t[4], @x[4], @x[4], #12
veor @x[3], @x[3], @t[3]
vext.8 @t[5], @x[5], @x[5], #12
veor @x[4], @x[4], @t[4]
vext.8 @t[6], @x[6], @x[6], #12
veor @x[5], @x[5], @t[5]
vext.8 @t[7], @x[7], @x[7], #12
veor @x[6], @x[6], @t[6]
veor @t[1], @t[1], @x[0]
veor @x[7], @x[7], @t[7]
vext.8 @x[0], @x[0], @x[0], #8 @ (x0 ^ (x0 <<< 32)) <<< 64)
veor @t[2], @t[2], @x[1]
veor @t[0], @t[0], @x[7]
veor @t[1], @t[1], @x[7]
vext.8 @x[1], @x[1], @x[1], #8
veor @t[5], @t[5], @x[4]
veor @x[0], @x[0], @t[0]
veor @t[6], @t[6], @x[5]
veor @x[1], @x[1], @t[1]
vext.8 @t[0], @x[4], @x[4], #8
veor @t[4], @t[4], @x[3]
vext.8 @t[1], @x[5], @x[5], #8
veor @t[7], @t[7], @x[6]
vext.8 @x[4], @x[3], @x[3], #8
veor @t[3], @t[3], @x[2]
vext.8 @x[5], @x[7], @x[7], #8
veor @t[4], @t[4], @x[7]
vext.8 @x[3], @x[6], @x[6], #8
veor @t[3], @t[3], @x[7]
vext.8 @x[6], @x[2], @x[2], #8
veor @x[7], @t[1], @t[5]
___
$code.=<<___ if (!$inv);
veor @x[2], @t[0], @t[4]
veor @x[4], @x[4], @t[3]
veor @x[5], @x[5], @t[7]
veor @x[3], @x[3], @t[6]
@ vmov @x[2], @t[0]
veor @x[6], @x[6], @t[2]
@ vmov @x[7], @t[1]
___
$code.=<<___ if ($inv);
veor @t[3], @t[3], @x[4]
veor @x[5], @x[5], @t[7]
veor @x[2], @x[3], @t[6]
veor @x[3], @t[0], @t[4]
veor @x[4], @x[6], @t[2]
vmov @x[6], @t[3]
@ vmov @x[7], @t[1]
___
}
sub InvMixColumns_orig {
my @x=@_[0..7];
my @t=@_[8..15];
$code.=<<___;
@ multiplication by 0x0e
vext.8 @t[7], @x[7], @x[7], #12
vmov @t[2], @x[2]
veor @x[2], @x[2], @x[5] @ 2 5
veor @x[7], @x[7], @x[5] @ 7 5
vext.8 @t[0], @x[0], @x[0], #12
vmov @t[5], @x[5]
veor @x[5], @x[5], @x[0] @ 5 0 [1]
veor @x[0], @x[0], @x[1] @ 0 1
vext.8 @t[1], @x[1], @x[1], #12
veor @x[1], @x[1], @x[2] @ 1 25
veor @x[0], @x[0], @x[6] @ 01 6 [2]
vext.8 @t[3], @x[3], @x[3], #12
veor @x[1], @x[1], @x[3] @ 125 3 [4]
veor @x[2], @x[2], @x[0] @ 25 016 [3]
veor @x[3], @x[3], @x[7] @ 3 75
veor @x[7], @x[7], @x[6] @ 75 6 [0]
vext.8 @t[6], @x[6], @x[6], #12
vmov @t[4], @x[4]
veor @x[6], @x[6], @x[4] @ 6 4
veor @x[4], @x[4], @x[3] @ 4 375 [6]
veor @x[3], @x[3], @x[7] @ 375 756=36
veor @x[6], @x[6], @t[5] @ 64 5 [7]
veor @x[3], @x[3], @t[2] @ 36 2
vext.8 @t[5], @t[5], @t[5], #12
veor @x[3], @x[3], @t[4] @ 362 4 [5]
___
my @y = @x[7,5,0,2,1,3,4,6];
$code.=<<___;
@ multiplication by 0x0b
veor @y[1], @y[1], @y[0]
veor @y[0], @y[0], @t[0]
vext.8 @t[2], @t[2], @t[2], #12
veor @y[1], @y[1], @t[1]
veor @y[0], @y[0], @t[5]
vext.8 @t[4], @t[4], @t[4], #12
veor @y[1], @y[1], @t[6]
veor @y[0], @y[0], @t[7]
veor @t[7], @t[7], @t[6] @ clobber t[7]
veor @y[3], @y[3], @t[0]
veor @y[1], @y[1], @y[0]
vext.8 @t[0], @t[0], @t[0], #12
veor @y[2], @y[2], @t[1]
veor @y[4], @y[4], @t[1]
vext.8 @t[1], @t[1], @t[1], #12
veor @y[2], @y[2], @t[2]
veor @y[3], @y[3], @t[2]
veor @y[5], @y[5], @t[2]
veor @y[2], @y[2], @t[7]
vext.8 @t[2], @t[2], @t[2], #12
veor @y[3], @y[3], @t[3]
veor @y[6], @y[6], @t[3]
veor @y[4], @y[4], @t[3]
veor @y[7], @y[7], @t[4]
vext.8 @t[3], @t[3], @t[3], #12
veor @y[5], @y[5], @t[4]
veor @y[7], @y[7], @t[7]
veor @t[7], @t[7], @t[5] @ clobber t[7] even more
veor @y[3], @y[3], @t[5]
veor @y[4], @y[4], @t[4]
veor @y[5], @y[5], @t[7]
vext.8 @t[4], @t[4], @t[4], #12
veor @y[6], @y[6], @t[7]
veor @y[4], @y[4], @t[7]
veor @t[7], @t[7], @t[5]
vext.8 @t[5], @t[5], @t[5], #12
@ multiplication by 0x0d
veor @y[4], @y[4], @y[7]
veor @t[7], @t[7], @t[6] @ restore t[7]
veor @y[7], @y[7], @t[4]
vext.8 @t[6], @t[6], @t[6], #12
veor @y[2], @y[2], @t[0]
veor @y[7], @y[7], @t[5]
vext.8 @t[7], @t[7], @t[7], #12
veor @y[2], @y[2], @t[2]
veor @y[3], @y[3], @y[1]
veor @y[1], @y[1], @t[1]
veor @y[0], @y[0], @t[0]
veor @y[3], @y[3], @t[0]
veor @y[1], @y[1], @t[5]
veor @y[0], @y[0], @t[5]
vext.8 @t[0], @t[0], @t[0], #12
veor @y[1], @y[1], @t[7]
veor @y[0], @y[0], @t[6]
veor @y[3], @y[3], @y[1]
veor @y[4], @y[4], @t[1]
vext.8 @t[1], @t[1], @t[1], #12
veor @y[7], @y[7], @t[7]
veor @y[4], @y[4], @t[2]
veor @y[5], @y[5], @t[2]
veor @y[2], @y[2], @t[6]
veor @t[6], @t[6], @t[3] @ clobber t[6]
vext.8 @t[2], @t[2], @t[2], #12
veor @y[4], @y[4], @y[7]
veor @y[3], @y[3], @t[6]
veor @y[6], @y[6], @t[6]
veor @y[5], @y[5], @t[5]
vext.8 @t[5], @t[5], @t[5], #12
veor @y[6], @y[6], @t[4]
vext.8 @t[4], @t[4], @t[4], #12
veor @y[5], @y[5], @t[6]
veor @y[6], @y[6], @t[7]
vext.8 @t[7], @t[7], @t[7], #12
veor @t[6], @t[6], @t[3] @ restore t[6]
vext.8 @t[3], @t[3], @t[3], #12
@ multiplication by 0x09
veor @y[4], @y[4], @y[1]
veor @t[1], @t[1], @y[1] @ t[1]=y[1]
veor @t[0], @t[0], @t[5] @ clobber t[0]
vext.8 @t[6], @t[6], @t[6], #12
veor @t[1], @t[1], @t[5]
veor @y[3], @y[3], @t[0]
veor @t[0], @t[0], @y[0] @ t[0]=y[0]
veor @t[1], @t[1], @t[6]
veor @t[6], @t[6], @t[7] @ clobber t[6]
veor @y[4], @y[4], @t[1]
veor @y[7], @y[7], @t[4]
veor @y[6], @y[6], @t[3]
veor @y[5], @y[5], @t[2]
veor @t[4], @t[4], @y[4] @ t[4]=y[4]
veor @t[3], @t[3], @y[3] @ t[3]=y[3]
veor @t[5], @t[5], @y[5] @ t[5]=y[5]
veor @t[2], @t[2], @y[2] @ t[2]=y[2]
veor @t[3], @t[3], @t[7]
veor @XMM[5], @t[5], @t[6]
veor @XMM[6], @t[6], @y[6] @ t[6]=y[6]
veor @XMM[2], @t[2], @t[6]
veor @XMM[7], @t[7], @y[7] @ t[7]=y[7]
vmov @XMM[0], @t[0]
vmov @XMM[1], @t[1]
@ vmov @XMM[2], @t[2]
vmov @XMM[3], @t[3]
vmov @XMM[4], @t[4]
@ vmov @XMM[5], @t[5]
@ vmov @XMM[6], @t[6]
@ vmov @XMM[7], @t[7]
___
}
sub InvMixColumns {
my @x=@_[0..7];
my @t=@_[8..15];
# Thanks to Jussi Kivilinna for providing pointer to
#
# | 0e 0b 0d 09 | | 02 03 01 01 | | 05 00 04 00 |
# | 09 0e 0b 0d | = | 01 02 03 01 | x | 00 05 00 04 |
# | 0d 09 0e 0b | | 01 01 02 03 | | 04 00 05 00 |
# | 0b 0d 09 0e | | 03 01 01 02 | | 00 04 00 05 |
$code.=<<___;
@ multiplication by 0x05-0x00-0x04-0x00
vext.8 @t[0], @x[0], @x[0], #8
vext.8 @t[6], @x[6], @x[6], #8
vext.8 @t[7], @x[7], @x[7], #8
veor @t[0], @t[0], @x[0]
vext.8 @t[1], @x[1], @x[1], #8
veor @t[6], @t[6], @x[6]
vext.8 @t[2], @x[2], @x[2], #8
veor @t[7], @t[7], @x[7]
vext.8 @t[3], @x[3], @x[3], #8
veor @t[1], @t[1], @x[1]
vext.8 @t[4], @x[4], @x[4], #8
veor @t[2], @t[2], @x[2]
vext.8 @t[5], @x[5], @x[5], #8
veor @t[3], @t[3], @x[3]
veor @t[4], @t[4], @x[4]
veor @t[5], @t[5], @x[5]
veor @x[0], @x[0], @t[6]
veor @x[1], @x[1], @t[6]
veor @x[2], @x[2], @t[0]
veor @x[4], @x[4], @t[2]
veor @x[3], @x[3], @t[1]
veor @x[1], @x[1], @t[7]
veor @x[2], @x[2], @t[7]
veor @x[4], @x[4], @t[6]
veor @x[5], @x[5], @t[3]
veor @x[3], @x[3], @t[6]
veor @x[6], @x[6], @t[4]
veor @x[4], @x[4], @t[7]
veor @x[5], @x[5], @t[7]
veor @x[7], @x[7], @t[5]
___
&MixColumns (@x,@t,1); # flipped 2<->3 and 4<->6
}
sub swapmove {
my ($a,$b,$n,$mask,$t)=@_;
$code.=<<___;
vshr.u64 $t, $b, #$n
veor $t, $t, $a
vand $t, $t, $mask
veor $a, $a, $t
vshl.u64 $t, $t, #$n
veor $b, $b, $t
___
}
sub swapmove2x {
my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_;
$code.=<<___;
vshr.u64 $t0, $b0, #$n
vshr.u64 $t1, $b1, #$n
veor $t0, $t0, $a0
veor $t1, $t1, $a1
vand $t0, $t0, $mask
vand $t1, $t1, $mask
veor $a0, $a0, $t0
vshl.u64 $t0, $t0, #$n
veor $a1, $a1, $t1
vshl.u64 $t1, $t1, #$n
veor $b0, $b0, $t0
veor $b1, $b1, $t1
___
}
sub bitslice {
my @x=reverse(@_[0..7]);
my ($t0,$t1,$t2,$t3)=@_[8..11];
$code.=<<___;
vmov.i8 $t0,#0x55 @ compose .LBS0
vmov.i8 $t1,#0x33 @ compose .LBS1
___
&swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3);
&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
$code.=<<___;
vmov.i8 $t0,#0x0f @ compose .LBS2
___
&swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3);
&swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
&swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3);
&swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3);
}
$code.=<<___;
#ifndef __KERNEL__
# include "arm_arch.h"
# define VFP_ABI_PUSH vstmdb sp!,{d8-d15}
# define VFP_ABI_POP vldmia sp!,{d8-d15}
# define VFP_ABI_FRAME 0x40
#else
# define VFP_ABI_PUSH
# define VFP_ABI_POP
# define VFP_ABI_FRAME 0
# define BSAES_ASM_EXTENDED_KEY
# define XTS_CHAIN_TWEAK
# define __ARM_ARCH__ __LINUX_ARM_ARCH__
# define __ARM_MAX_ARCH__ 7
#endif
#ifdef __thumb__
# define adrl adr
#endif
#if __ARM_MAX_ARCH__>=7
.arch armv7-a
.fpu neon
.syntax unified @ ARMv7-capable assembler is expected to handle this
#if defined(__thumb2__) && !defined(__APPLE__)
.thumb
#else
.code 32
# undef __thumb2__
#endif
.text
.type _bsaes_decrypt8,%function
.align 4
_bsaes_decrypt8:
adr $const,.
vldmia $key!, {@XMM[9]} @ round 0 key
#if defined(__thumb2__) || defined(__APPLE__)
adr $const,.LM0ISR
#else
add $const,$const,#.LM0ISR-_bsaes_decrypt8
#endif
vldmia $const!, {@XMM[8]} @ .LM0ISR
veor @XMM[10], @XMM[0], @XMM[9] @ xor with round0 key
veor @XMM[11], @XMM[1], @XMM[9]
vtbl.8 `&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])`
veor @XMM[12], @XMM[2], @XMM[9]
vtbl.8 `&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])`
veor @XMM[13], @XMM[3], @XMM[9]
vtbl.8 `&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])`
veor @XMM[14], @XMM[4], @XMM[9]
vtbl.8 `&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])`
veor @XMM[15], @XMM[5], @XMM[9]
vtbl.8 `&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])`
veor @XMM[10], @XMM[6], @XMM[9]
vtbl.8 `&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])`
veor @XMM[11], @XMM[7], @XMM[9]
vtbl.8 `&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])`
vtbl.8 `&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])`
___
&bitslice (@XMM[0..7, 8..11]);
$code.=<<___;
sub $rounds,$rounds,#1
b .Ldec_sbox
.align 4
.Ldec_loop:
___
&ShiftRows (@XMM[0..7, 8..12]);
$code.=".Ldec_sbox:\n";
&InvSbox (@XMM[0..7, 8..15]);
$code.=<<___;
subs $rounds,$rounds,#1
bcc .Ldec_done
___
&InvMixColumns (@XMM[0,1,6,4,2,7,3,5, 8..15]);
$code.=<<___;
vldmia $const, {@XMM[12]} @ .LISR
ite eq @ Thumb2 thing, sanity check in ARM
addeq $const,$const,#0x10
bne .Ldec_loop
vldmia $const, {@XMM[12]} @ .LISRM0
b .Ldec_loop
.align 4
.Ldec_done:
___
&bitslice (@XMM[0,1,6,4,2,7,3,5, 8..11]);
$code.=<<___;
vldmia $key, {@XMM[8]} @ last round key
veor @XMM[6], @XMM[6], @XMM[8]
veor @XMM[4], @XMM[4], @XMM[8]
veor @XMM[2], @XMM[2], @XMM[8]
veor @XMM[7], @XMM[7], @XMM[8]
veor @XMM[3], @XMM[3], @XMM[8]
veor @XMM[5], @XMM[5], @XMM[8]
veor @XMM[0], @XMM[0], @XMM[8]
veor @XMM[1], @XMM[1], @XMM[8]
bx lr
.size _bsaes_decrypt8,.-_bsaes_decrypt8
.type _bsaes_const,%object
.align 6
_bsaes_const:
.LM0ISR: @ InvShiftRows constants
.quad 0x0a0e0206070b0f03, 0x0004080c0d010509
.LISR:
.quad 0x0504070602010003, 0x0f0e0d0c080b0a09
.LISRM0:
.quad 0x01040b0e0205080f, 0x0306090c00070a0d
.LM0SR: @ ShiftRows constants
.quad 0x0a0e02060f03070b, 0x0004080c05090d01
.LSR:
.quad 0x0504070600030201, 0x0f0e0d0c0a09080b
.LSRM0:
.quad 0x0304090e00050a0f, 0x01060b0c0207080d
.LM0:
.quad 0x02060a0e03070b0f, 0x0004080c0105090d
.LREVM0SR:
.quad 0x090d01050c000408, 0x03070b0f060a0e02
.asciz "Bit-sliced AES for NEON, CRYPTOGAMS by <appro\@openssl.org>"
.align 6
.size _bsaes_const,.-_bsaes_const
.type _bsaes_encrypt8,%function
.align 4
_bsaes_encrypt8:
adr $const,.
vldmia $key!, {@XMM[9]} @ round 0 key
#if defined(__thumb2__) || defined(__APPLE__)
adr $const,.LM0SR
#else
sub $const,$const,#_bsaes_encrypt8-.LM0SR
#endif
vldmia $const!, {@XMM[8]} @ .LM0SR
_bsaes_encrypt8_alt:
veor @XMM[10], @XMM[0], @XMM[9] @ xor with round0 key
veor @XMM[11], @XMM[1], @XMM[9]
vtbl.8 `&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])`
veor @XMM[12], @XMM[2], @XMM[9]
vtbl.8 `&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])`
veor @XMM[13], @XMM[3], @XMM[9]
vtbl.8 `&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])`
veor @XMM[14], @XMM[4], @XMM[9]
vtbl.8 `&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])`
veor @XMM[15], @XMM[5], @XMM[9]
vtbl.8 `&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])`
veor @XMM[10], @XMM[6], @XMM[9]
vtbl.8 `&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])`
veor @XMM[11], @XMM[7], @XMM[9]
vtbl.8 `&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])`
vtbl.8 `&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])`
vtbl.8 `&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])`
_bsaes_encrypt8_bitslice:
___
&bitslice (@XMM[0..7, 8..11]);
$code.=<<___;
sub $rounds,$rounds,#1
b .Lenc_sbox
.align 4
.Lenc_loop:
___
&ShiftRows (@XMM[0..7, 8..12]);
$code.=".Lenc_sbox:\n";
&Sbox (@XMM[0..7, 8..15]);
$code.=<<___;
subs $rounds,$rounds,#1
bcc .Lenc_done
___
&MixColumns (@XMM[0,1,4,6,3,7,2,5, 8..15]);
$code.=<<___;
vldmia $const, {@XMM[12]} @ .LSR
ite eq @ Thumb2 thing, samity check in ARM
addeq $const,$const,#0x10
bne .Lenc_loop
vldmia $const, {@XMM[12]} @ .LSRM0
b .Lenc_loop
.align 4
.Lenc_done:
___
# output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb
&bitslice (@XMM[0,1,4,6,3,7,2,5, 8..11]);
$code.=<<___;
vldmia $key, {@XMM[8]} @ last round key
veor @XMM[4], @XMM[4], @XMM[8]
veor @XMM[6], @XMM[6], @XMM[8]
veor @XMM[3], @XMM[3], @XMM[8]
veor @XMM[7], @XMM[7], @XMM[8]
veor @XMM[2], @XMM[2], @XMM[8]
veor @XMM[5], @XMM[5], @XMM[8]
veor @XMM[0], @XMM[0], @XMM[8]
veor @XMM[1], @XMM[1], @XMM[8]
bx lr
.size _bsaes_encrypt8,.-_bsaes_encrypt8
___
}
{
my ($out,$inp,$rounds,$const)=("r12","r4","r5","r6");
sub bitslice_key {
my @x=reverse(@_[0..7]);
my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12];
&swapmove (@x[0,1],1,$bs0,$t2,$t3);
$code.=<<___;
@ &swapmove(@x[2,3],1,$t0,$t2,$t3);
vmov @x[2], @x[0]
vmov @x[3], @x[1]
___
#&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
&swapmove2x (@x[0,2,1,3],2,$bs1,$t2,$t3);
$code.=<<___;
@ &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
vmov @x[4], @x[0]
vmov @x[6], @x[2]
vmov @x[5], @x[1]
vmov @x[7], @x[3]
___
&swapmove2x (@x[0,4,1,5],4,$bs2,$t2,$t3);
&swapmove2x (@x[2,6,3,7],4,$bs2,$t2,$t3);
}
$code.=<<___;
.type _bsaes_key_convert,%function
.align 4
_bsaes_key_convert:
adr $const,.
vld1.8 {@XMM[7]}, [$inp]! @ load round 0 key
#if defined(__thumb2__) || defined(__APPLE__)
adr $const,.LM0
#else
sub $const,$const,#_bsaes_key_convert-.LM0
#endif
vld1.8 {@XMM[15]}, [$inp]! @ load round 1 key
vmov.i8 @XMM[8], #0x01 @ bit masks
vmov.i8 @XMM[9], #0x02
vmov.i8 @XMM[10], #0x04
vmov.i8 @XMM[11], #0x08
vmov.i8 @XMM[12], #0x10
vmov.i8 @XMM[13], #0x20
vldmia $const, {@XMM[14]} @ .LM0
#ifdef __ARMEL__
vrev32.8 @XMM[7], @XMM[7]
vrev32.8 @XMM[15], @XMM[15]
#endif
sub $rounds,$rounds,#1
vstmia $out!, {@XMM[7]} @ save round 0 key
b .Lkey_loop
.align 4
.Lkey_loop:
vtbl.8 `&Dlo(@XMM[7])`,{@XMM[15]},`&Dlo(@XMM[14])`
vtbl.8 `&Dhi(@XMM[7])`,{@XMM[15]},`&Dhi(@XMM[14])`
vmov.i8 @XMM[6], #0x40
vmov.i8 @XMM[15], #0x80
vtst.8 @XMM[0], @XMM[7], @XMM[8]
vtst.8 @XMM[1], @XMM[7], @XMM[9]
vtst.8 @XMM[2], @XMM[7], @XMM[10]
vtst.8 @XMM[3], @XMM[7], @XMM[11]
vtst.8 @XMM[4], @XMM[7], @XMM[12]
vtst.8 @XMM[5], @XMM[7], @XMM[13]
vtst.8 @XMM[6], @XMM[7], @XMM[6]
vtst.8 @XMM[7], @XMM[7], @XMM[15]
vld1.8 {@XMM[15]}, [$inp]! @ load next round key
vmvn @XMM[0], @XMM[0] @ "pnot"
vmvn @XMM[1], @XMM[1]
vmvn @XMM[5], @XMM[5]
vmvn @XMM[6], @XMM[6]
#ifdef __ARMEL__
vrev32.8 @XMM[15], @XMM[15]
#endif
subs $rounds,$rounds,#1
vstmia $out!,{@XMM[0]-@XMM[7]} @ write bit-sliced round key
bne .Lkey_loop
vmov.i8 @XMM[7],#0x63 @ compose .L63
@ don't save last round key
bx lr
.size _bsaes_key_convert,.-_bsaes_key_convert
___
}
if (0) { # following four functions are unsupported interface
# used for benchmarking...
$code.=<<___;
.globl bsaes_enc_key_convert
.type bsaes_enc_key_convert,%function
.align 4
bsaes_enc_key_convert:
stmdb sp!,{r4-r6,lr}
vstmdb sp!,{d8-d15} @ ABI specification says so
ldr r5,[$inp,#240] @ pass rounds
mov r4,$inp @ pass key
mov r12,$out @ pass key schedule
bl _bsaes_key_convert
veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key
vstmia r12, {@XMM[7]} @ save last round key
vldmia sp!,{d8-d15}
ldmia sp!,{r4-r6,pc}
.size bsaes_enc_key_convert,.-bsaes_enc_key_convert
.globl bsaes_encrypt_128
.type bsaes_encrypt_128,%function
.align 4
bsaes_encrypt_128:
stmdb sp!,{r4-r6,lr}
vstmdb sp!,{d8-d15} @ ABI specification says so
.Lenc128_loop:
vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input
vld1.8 {@XMM[2]-@XMM[3]}, [$inp]!
mov r4,$key @ pass the key
vld1.8 {@XMM[4]-@XMM[5]}, [$inp]!
mov r5,#10 @ pass rounds
vld1.8 {@XMM[6]-@XMM[7]}, [$inp]!
bl _bsaes_encrypt8
vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
vst1.8 {@XMM[4]}, [$out]!
vst1.8 {@XMM[6]}, [$out]!
vst1.8 {@XMM[3]}, [$out]!
vst1.8 {@XMM[7]}, [$out]!
vst1.8 {@XMM[2]}, [$out]!
subs $len,$len,#0x80
vst1.8 {@XMM[5]}, [$out]!
bhi .Lenc128_loop
vldmia sp!,{d8-d15}
ldmia sp!,{r4-r6,pc}
.size bsaes_encrypt_128,.-bsaes_encrypt_128
.globl bsaes_dec_key_convert
.type bsaes_dec_key_convert,%function
.align 4
bsaes_dec_key_convert:
stmdb sp!,{r4-r6,lr}
vstmdb sp!,{d8-d15} @ ABI specification says so
ldr r5,[$inp,#240] @ pass rounds
mov r4,$inp @ pass key
mov r12,$out @ pass key schedule
bl _bsaes_key_convert
vldmia $out, {@XMM[6]}
vstmia r12, {@XMM[15]} @ save last round key
veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key
vstmia $out, {@XMM[7]}
vldmia sp!,{d8-d15}
ldmia sp!,{r4-r6,pc}
.size bsaes_dec_key_convert,.-bsaes_dec_key_convert
.globl bsaes_decrypt_128
.type bsaes_decrypt_128,%function
.align 4
bsaes_decrypt_128:
stmdb sp!,{r4-r6,lr}
vstmdb sp!,{d8-d15} @ ABI specification says so
.Ldec128_loop:
vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input
vld1.8 {@XMM[2]-@XMM[3]}, [$inp]!
mov r4,$key @ pass the key
vld1.8 {@XMM[4]-@XMM[5]}, [$inp]!
mov r5,#10 @ pass rounds
vld1.8 {@XMM[6]-@XMM[7]}, [$inp]!
bl _bsaes_decrypt8
vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
vst1.8 {@XMM[6]}, [$out]!
vst1.8 {@XMM[4]}, [$out]!
vst1.8 {@XMM[2]}, [$out]!
vst1.8 {@XMM[7]}, [$out]!
vst1.8 {@XMM[3]}, [$out]!
subs $len,$len,#0x80
vst1.8 {@XMM[5]}, [$out]!
bhi .Ldec128_loop
vldmia sp!,{d8-d15}
ldmia sp!,{r4-r6,pc}
.size bsaes_decrypt_128,.-bsaes_decrypt_128
___
}
{
my ($inp,$out,$len,$key, $ivp,$fp,$rounds)=map("r$_",(0..3,8..10));
my ($keysched)=("sp");
$code.=<<___;
.extern AES_cbc_encrypt
.extern AES_decrypt
.global ossl_bsaes_cbc_encrypt
.type ossl_bsaes_cbc_encrypt,%function
.align 5
ossl_bsaes_cbc_encrypt:
#ifndef __KERNEL__
cmp $len, #128
#ifndef __thumb__
blo AES_cbc_encrypt
#else
bhs .Lcbc_do_bsaes
b AES_cbc_encrypt
.Lcbc_do_bsaes:
#endif
#endif
@ it is up to the caller to make sure we are called with enc == 0
mov ip, sp
stmdb sp!, {r4-r10, lr}
VFP_ABI_PUSH
ldr $ivp, [ip] @ IV is 1st arg on the stack
mov $len, $len, lsr#4 @ len in 16 byte blocks
sub sp, #0x10 @ scratch space to carry over the IV
mov $fp, sp @ save sp
ldr $rounds, [$key, #240] @ get # of rounds
#ifndef BSAES_ASM_EXTENDED_KEY
@ allocate the key schedule on the stack
sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key
add r12, #`128-32` @ sifze of bit-slices key schedule
@ populate the key schedule
mov r4, $key @ pass key
mov r5, $rounds @ pass # of rounds
mov sp, r12 @ sp is $keysched
bl _bsaes_key_convert
vldmia $keysched, {@XMM[6]}
vstmia r12, {@XMM[15]} @ save last round key
veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key
vstmia $keysched, {@XMM[7]}
#else
ldr r12, [$key, #244]
eors r12, #1
beq 0f
@ populate the key schedule
str r12, [$key, #244]
mov r4, $key @ pass key
mov r5, $rounds @ pass # of rounds
add r12, $key, #248 @ pass key schedule
bl _bsaes_key_convert
add r4, $key, #248
vldmia r4, {@XMM[6]}
vstmia r12, {@XMM[15]} @ save last round key
veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key
vstmia r4, {@XMM[7]}
.align 2
0:
#endif
vld1.8 {@XMM[15]}, [$ivp] @ load IV
b .Lcbc_dec_loop
.align 4
.Lcbc_dec_loop:
subs $len, $len, #0x8
bmi .Lcbc_dec_loop_finish
vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input
vld1.8 {@XMM[2]-@XMM[3]}, [$inp]!
#ifndef BSAES_ASM_EXTENDED_KEY
mov r4, $keysched @ pass the key
#else
add r4, $key, #248
#endif
vld1.8 {@XMM[4]-@XMM[5]}, [$inp]!
mov r5, $rounds
vld1.8 {@XMM[6]-@XMM[7]}, [$inp]
sub $inp, $inp, #0x60
vstmia $fp, {@XMM[15]} @ put aside IV
bl _bsaes_decrypt8
vldmia $fp, {@XMM[14]} @ reload IV
vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
veor @XMM[1], @XMM[1], @XMM[8]
veor @XMM[6], @XMM[6], @XMM[9]
vld1.8 {@XMM[12]-@XMM[13]}, [$inp]!
veor @XMM[4], @XMM[4], @XMM[10]
veor @XMM[2], @XMM[2], @XMM[11]
vld1.8 {@XMM[14]-@XMM[15]}, [$inp]!
veor @XMM[7], @XMM[7], @XMM[12]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
veor @XMM[3], @XMM[3], @XMM[13]
vst1.8 {@XMM[6]}, [$out]!
veor @XMM[5], @XMM[5], @XMM[14]
vst1.8 {@XMM[4]}, [$out]!
vst1.8 {@XMM[2]}, [$out]!
vst1.8 {@XMM[7]}, [$out]!
vst1.8 {@XMM[3]}, [$out]!
vst1.8 {@XMM[5]}, [$out]!
b .Lcbc_dec_loop
.Lcbc_dec_loop_finish:
adds $len, $len, #8
beq .Lcbc_dec_done
vld1.8 {@XMM[0]}, [$inp]! @ load input
cmp $len, #2
blo .Lcbc_dec_one
vld1.8 {@XMM[1]}, [$inp]!
#ifndef BSAES_ASM_EXTENDED_KEY
mov r4, $keysched @ pass the key
#else
add r4, $key, #248
#endif
mov r5, $rounds
vstmia $fp, {@XMM[15]} @ put aside IV
beq .Lcbc_dec_two
vld1.8 {@XMM[2]}, [$inp]!
cmp $len, #4
blo .Lcbc_dec_three
vld1.8 {@XMM[3]}, [$inp]!
beq .Lcbc_dec_four
vld1.8 {@XMM[4]}, [$inp]!
cmp $len, #6
blo .Lcbc_dec_five
vld1.8 {@XMM[5]}, [$inp]!
beq .Lcbc_dec_six
vld1.8 {@XMM[6]}, [$inp]!
sub $inp, $inp, #0x70
bl _bsaes_decrypt8
vldmia $fp, {@XMM[14]} @ reload IV
vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
veor @XMM[1], @XMM[1], @XMM[8]
veor @XMM[6], @XMM[6], @XMM[9]
vld1.8 {@XMM[12]-@XMM[13]}, [$inp]!
veor @XMM[4], @XMM[4], @XMM[10]
veor @XMM[2], @XMM[2], @XMM[11]
vld1.8 {@XMM[15]}, [$inp]!
veor @XMM[7], @XMM[7], @XMM[12]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
veor @XMM[3], @XMM[3], @XMM[13]
vst1.8 {@XMM[6]}, [$out]!
vst1.8 {@XMM[4]}, [$out]!
vst1.8 {@XMM[2]}, [$out]!
vst1.8 {@XMM[7]}, [$out]!
vst1.8 {@XMM[3]}, [$out]!
b .Lcbc_dec_done
.align 4
.Lcbc_dec_six:
sub $inp, $inp, #0x60
bl _bsaes_decrypt8
vldmia $fp,{@XMM[14]} @ reload IV
vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
veor @XMM[1], @XMM[1], @XMM[8]
veor @XMM[6], @XMM[6], @XMM[9]
vld1.8 {@XMM[12]}, [$inp]!
veor @XMM[4], @XMM[4], @XMM[10]
veor @XMM[2], @XMM[2], @XMM[11]
vld1.8 {@XMM[15]}, [$inp]!
veor @XMM[7], @XMM[7], @XMM[12]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
vst1.8 {@XMM[6]}, [$out]!
vst1.8 {@XMM[4]}, [$out]!
vst1.8 {@XMM[2]}, [$out]!
vst1.8 {@XMM[7]}, [$out]!
b .Lcbc_dec_done
.align 4
.Lcbc_dec_five:
sub $inp, $inp, #0x50
bl _bsaes_decrypt8
vldmia $fp, {@XMM[14]} @ reload IV
vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
veor @XMM[1], @XMM[1], @XMM[8]
veor @XMM[6], @XMM[6], @XMM[9]
vld1.8 {@XMM[15]}, [$inp]!
veor @XMM[4], @XMM[4], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
veor @XMM[2], @XMM[2], @XMM[11]
vst1.8 {@XMM[6]}, [$out]!
vst1.8 {@XMM[4]}, [$out]!
vst1.8 {@XMM[2]}, [$out]!
b .Lcbc_dec_done
.align 4
.Lcbc_dec_four:
sub $inp, $inp, #0x40
bl _bsaes_decrypt8
vldmia $fp, {@XMM[14]} @ reload IV
vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
vld1.8 {@XMM[10]}, [$inp]!
veor @XMM[1], @XMM[1], @XMM[8]
veor @XMM[6], @XMM[6], @XMM[9]
vld1.8 {@XMM[15]}, [$inp]!
veor @XMM[4], @XMM[4], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
vst1.8 {@XMM[6]}, [$out]!
vst1.8 {@XMM[4]}, [$out]!
b .Lcbc_dec_done
.align 4
.Lcbc_dec_three:
sub $inp, $inp, #0x30
bl _bsaes_decrypt8
vldmia $fp, {@XMM[14]} @ reload IV
vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
vld1.8 {@XMM[15]}, [$inp]!
veor @XMM[1], @XMM[1], @XMM[8]
veor @XMM[6], @XMM[6], @XMM[9]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
vst1.8 {@XMM[6]}, [$out]!
b .Lcbc_dec_done
.align 4
.Lcbc_dec_two:
sub $inp, $inp, #0x20
bl _bsaes_decrypt8
vldmia $fp, {@XMM[14]} @ reload IV
vld1.8 {@XMM[8]}, [$inp]! @ reload input
veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
vld1.8 {@XMM[15]}, [$inp]! @ reload input
veor @XMM[1], @XMM[1], @XMM[8]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
b .Lcbc_dec_done
.align 4
.Lcbc_dec_one:
sub $inp, $inp, #0x10
mov $rounds, $out @ save original out pointer
mov $out, $fp @ use the iv scratch space as out buffer
mov r2, $key
vmov @XMM[4],@XMM[15] @ just in case ensure that IV
vmov @XMM[5],@XMM[0] @ and input are preserved
bl AES_decrypt
vld1.8 {@XMM[0]}, [$fp] @ load result
veor @XMM[0], @XMM[0], @XMM[4] @ ^= IV
vmov @XMM[15], @XMM[5] @ @XMM[5] holds input
vst1.8 {@XMM[0]}, [$rounds] @ write output
.Lcbc_dec_done:
#ifndef BSAES_ASM_EXTENDED_KEY
vmov.i32 q0, #0
vmov.i32 q1, #0
.Lcbc_dec_bzero: @ wipe key schedule [if any]
vstmia $keysched!, {q0-q1}
cmp $keysched, $fp
bne .Lcbc_dec_bzero
#endif
mov sp, $fp
add sp, #0x10 @ add sp,$fp,#0x10 is no good for thumb
vst1.8 {@XMM[15]}, [$ivp] @ return IV
VFP_ABI_POP
ldmia sp!, {r4-r10, pc}
.size ossl_bsaes_cbc_encrypt,.-ossl_bsaes_cbc_encrypt
___
}
{
my ($inp,$out,$len,$key, $ctr,$fp,$rounds)=(map("r$_",(0..3,8..10)));
my $const = "r6"; # shared with _bsaes_encrypt8_alt
my $keysched = "sp";
$code.=<<___;
.extern AES_encrypt
.global ossl_bsaes_ctr32_encrypt_blocks
.type ossl_bsaes_ctr32_encrypt_blocks,%function
.align 5
ossl_bsaes_ctr32_encrypt_blocks:
cmp $len, #8 @ use plain AES for
blo .Lctr_enc_short @ small sizes
mov ip, sp
stmdb sp!, {r4-r10, lr}
VFP_ABI_PUSH
ldr $ctr, [ip] @ ctr is 1st arg on the stack
sub sp, sp, #0x10 @ scratch space to carry over the ctr
mov $fp, sp @ save sp
ldr $rounds, [$key, #240] @ get # of rounds
#ifndef BSAES_ASM_EXTENDED_KEY
@ allocate the key schedule on the stack
sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key
add r12, #`128-32` @ size of bit-sliced key schedule
@ populate the key schedule
mov r4, $key @ pass key
mov r5, $rounds @ pass # of rounds
mov sp, r12 @ sp is $keysched
bl _bsaes_key_convert
veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key
vstmia r12, {@XMM[7]} @ save last round key
vld1.8 {@XMM[0]}, [$ctr] @ load counter
#ifdef __APPLE__
mov $ctr, #:lower16:(.LREVM0SR-.LM0)
add $ctr, $const, $ctr
#else
add $ctr, $const, #.LREVM0SR-.LM0 @ borrow $ctr
#endif
vldmia $keysched, {@XMM[4]} @ load round0 key
#else
ldr r12, [$key, #244]
eors r12, #1
beq 0f
@ populate the key schedule
str r12, [$key, #244]
mov r4, $key @ pass key
mov r5, $rounds @ pass # of rounds
add r12, $key, #248 @ pass key schedule
bl _bsaes_key_convert
veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key
vstmia r12, {@XMM[7]} @ save last round key
.align 2
0: add r12, $key, #248
vld1.8 {@XMM[0]}, [$ctr] @ load counter
- adrl $ctr, .LREVM0SR @ borrow $ctr
+ add $ctr, $const, #.LREVM0SR-.LM0 @ borrow $ctr
vldmia r12, {@XMM[4]} @ load round0 key
sub sp, #0x10 @ place for adjusted round0 key
#endif
vmov.i32 @XMM[8],#1 @ compose 1<<96
veor @XMM[9],@XMM[9],@XMM[9]
vrev32.8 @XMM[0],@XMM[0]
vext.8 @XMM[8],@XMM[9],@XMM[8],#4
vrev32.8 @XMM[4],@XMM[4]
vadd.u32 @XMM[9],@XMM[8],@XMM[8] @ compose 2<<96
vstmia $keysched, {@XMM[4]} @ save adjusted round0 key
b .Lctr_enc_loop
.align 4
.Lctr_enc_loop:
vadd.u32 @XMM[10], @XMM[8], @XMM[9] @ compose 3<<96
vadd.u32 @XMM[1], @XMM[0], @XMM[8] @ +1
vadd.u32 @XMM[2], @XMM[0], @XMM[9] @ +2
vadd.u32 @XMM[3], @XMM[0], @XMM[10] @ +3
vadd.u32 @XMM[4], @XMM[1], @XMM[10]
vadd.u32 @XMM[5], @XMM[2], @XMM[10]
vadd.u32 @XMM[6], @XMM[3], @XMM[10]
vadd.u32 @XMM[7], @XMM[4], @XMM[10]
vadd.u32 @XMM[10], @XMM[5], @XMM[10] @ next counter
@ Borrow prologue from _bsaes_encrypt8 to use the opportunity
@ to flip byte order in 32-bit counter
vldmia $keysched, {@XMM[9]} @ load round0 key
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, $keysched, #0x10 @ pass next round key
#else
add r4, $key, #`248+16`
#endif
vldmia $ctr, {@XMM[8]} @ .LREVM0SR
mov r5, $rounds @ pass rounds
vstmia $fp, {@XMM[10]} @ save next counter
#ifdef __APPLE__
mov $const, #:lower16:(.LREVM0SR-.LSR)
sub $const, $ctr, $const
#else
sub $const, $ctr, #.LREVM0SR-.LSR @ pass constants
#endif
bl _bsaes_encrypt8_alt
subs $len, $len, #8
blo .Lctr_enc_loop_done
vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ load input
vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
veor @XMM[0], @XMM[8]
veor @XMM[1], @XMM[9]
vld1.8 {@XMM[12]-@XMM[13]}, [$inp]!
veor @XMM[4], @XMM[10]
veor @XMM[6], @XMM[11]
vld1.8 {@XMM[14]-@XMM[15]}, [$inp]!
veor @XMM[3], @XMM[12]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
veor @XMM[7], @XMM[13]
veor @XMM[2], @XMM[14]
vst1.8 {@XMM[4]}, [$out]!
veor @XMM[5], @XMM[15]
vst1.8 {@XMM[6]}, [$out]!
vmov.i32 @XMM[8], #1 @ compose 1<<96
vst1.8 {@XMM[3]}, [$out]!
veor @XMM[9], @XMM[9], @XMM[9]
vst1.8 {@XMM[7]}, [$out]!
vext.8 @XMM[8], @XMM[9], @XMM[8], #4
vst1.8 {@XMM[2]}, [$out]!
vadd.u32 @XMM[9],@XMM[8],@XMM[8] @ compose 2<<96
vst1.8 {@XMM[5]}, [$out]!
vldmia $fp, {@XMM[0]} @ load counter
bne .Lctr_enc_loop
b .Lctr_enc_done
.align 4
.Lctr_enc_loop_done:
add $len, $len, #8
vld1.8 {@XMM[8]}, [$inp]! @ load input
veor @XMM[0], @XMM[8]
vst1.8 {@XMM[0]}, [$out]! @ write output
cmp $len, #2
blo .Lctr_enc_done
vld1.8 {@XMM[9]}, [$inp]!
veor @XMM[1], @XMM[9]
vst1.8 {@XMM[1]}, [$out]!
beq .Lctr_enc_done
vld1.8 {@XMM[10]}, [$inp]!
veor @XMM[4], @XMM[10]
vst1.8 {@XMM[4]}, [$out]!
cmp $len, #4
blo .Lctr_enc_done
vld1.8 {@XMM[11]}, [$inp]!
veor @XMM[6], @XMM[11]
vst1.8 {@XMM[6]}, [$out]!
beq .Lctr_enc_done
vld1.8 {@XMM[12]}, [$inp]!
veor @XMM[3], @XMM[12]
vst1.8 {@XMM[3]}, [$out]!
cmp $len, #6
blo .Lctr_enc_done
vld1.8 {@XMM[13]}, [$inp]!
veor @XMM[7], @XMM[13]
vst1.8 {@XMM[7]}, [$out]!
beq .Lctr_enc_done
vld1.8 {@XMM[14]}, [$inp]
veor @XMM[2], @XMM[14]
vst1.8 {@XMM[2]}, [$out]!
.Lctr_enc_done:
vmov.i32 q0, #0
vmov.i32 q1, #0
#ifndef BSAES_ASM_EXTENDED_KEY
.Lctr_enc_bzero: @ wipe key schedule [if any]
vstmia $keysched!, {q0-q1}
cmp $keysched, $fp
bne .Lctr_enc_bzero
#else
vstmia $keysched, {q0-q1}
#endif
mov sp, $fp
add sp, #0x10 @ add sp,$fp,#0x10 is no good for thumb
VFP_ABI_POP
ldmia sp!, {r4-r10, pc} @ return
.align 4
.Lctr_enc_short:
ldr ip, [sp] @ ctr pointer is passed on stack
stmdb sp!, {r4-r8, lr}
mov r4, $inp @ copy arguments
mov r5, $out
mov r6, $len
mov r7, $key
ldr r8, [ip, #12] @ load counter LSW
vld1.8 {@XMM[1]}, [ip] @ load whole counter value
#ifdef __ARMEL__
rev r8, r8
#endif
sub sp, sp, #0x10
vst1.8 {@XMM[1]}, [sp] @ copy counter value
sub sp, sp, #0x10
.Lctr_enc_short_loop:
add r0, sp, #0x10 @ input counter value
mov r1, sp @ output on the stack
mov r2, r7 @ key
bl AES_encrypt
vld1.8 {@XMM[0]}, [r4]! @ load input
vld1.8 {@XMM[1]}, [sp] @ load encrypted counter
add r8, r8, #1
#ifdef __ARMEL__
rev r0, r8
str r0, [sp, #0x1c] @ next counter value
#else
str r8, [sp, #0x1c] @ next counter value
#endif
veor @XMM[0],@XMM[0],@XMM[1]
vst1.8 {@XMM[0]}, [r5]! @ store output
subs r6, r6, #1
bne .Lctr_enc_short_loop
vmov.i32 q0, #0
vmov.i32 q1, #0
vstmia sp!, {q0-q1}
ldmia sp!, {r4-r8, pc}
.size ossl_bsaes_ctr32_encrypt_blocks,.-ossl_bsaes_ctr32_encrypt_blocks
___
}
{
######################################################################
# void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len,
# const AES_KEY *key1, const AES_KEY *key2,
# const unsigned char iv[16]);
#
my ($inp,$out,$len,$key,$rounds,$magic,$fp)=(map("r$_",(7..10,1..3)));
my $const="r6"; # returned by _bsaes_key_convert
my $twmask=@XMM[5];
my @T=@XMM[6..7];
$code.=<<___;
.globl ossl_bsaes_xts_encrypt
.type ossl_bsaes_xts_encrypt,%function
.align 4
ossl_bsaes_xts_encrypt:
mov ip, sp
stmdb sp!, {r4-r10, lr} @ 0x20
VFP_ABI_PUSH
mov r6, sp @ future $fp
mov $inp, r0
mov $out, r1
mov $len, r2
mov $key, r3
sub r0, sp, #0x10 @ 0x10
bic r0, #0xf @ align at 16 bytes
mov sp, r0
#ifdef XTS_CHAIN_TWEAK
ldr r0, [ip] @ pointer to input tweak
#else
@ generate initial tweak
ldr r0, [ip, #4] @ iv[]
mov r1, sp
ldr r2, [ip, #0] @ key2
bl AES_encrypt
mov r0,sp @ pointer to initial tweak
#endif
ldr $rounds, [$key, #240] @ get # of rounds
mov $fp, r6
#ifndef BSAES_ASM_EXTENDED_KEY
@ allocate the key schedule on the stack
sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key
@ add r12, #`128-32` @ size of bit-sliced key schedule
sub r12, #`32+16` @ place for tweak[9]
@ populate the key schedule
mov r4, $key @ pass key
mov r5, $rounds @ pass # of rounds
mov sp, r12
add r12, #0x90 @ pass key schedule
bl _bsaes_key_convert
veor @XMM[7], @XMM[7], @XMM[15] @ fix up last round key
vstmia r12, {@XMM[7]} @ save last round key
#else
ldr r12, [$key, #244]
eors r12, #1
beq 0f
str r12, [$key, #244]
mov r4, $key @ pass key
mov r5, $rounds @ pass # of rounds
add r12, $key, #248 @ pass key schedule
bl _bsaes_key_convert
veor @XMM[7], @XMM[7], @XMM[15] @ fix up last round key
vstmia r12, {@XMM[7]}
.align 2
0: sub sp, #0x90 @ place for tweak[9]
#endif
vld1.8 {@XMM[8]}, [r0] @ initial tweak
adr $magic, .Lxts_magic
subs $len, #0x80
blo .Lxts_enc_short
b .Lxts_enc_loop
.align 4
.Lxts_enc_loop:
vldmia $magic, {$twmask} @ load XTS magic
vshr.s64 @T[0], @XMM[8], #63
mov r0, sp
vand @T[0], @T[0], $twmask
___
for($i=9;$i<16;$i++) {
$code.=<<___;
vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1]
vst1.64 {@XMM[$i-1]}, [r0,:128]!
vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
vshr.s64 @T[1], @XMM[$i], #63
veor @XMM[$i], @XMM[$i], @T[0]
vand @T[1], @T[1], $twmask
___
@T=reverse(@T);
$code.=<<___ if ($i>=10);
vld1.8 {@XMM[$i-10]}, [$inp]!
___
$code.=<<___ if ($i>=11);
veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
___
}
$code.=<<___;
vadd.u64 @XMM[8], @XMM[15], @XMM[15]
vst1.64 {@XMM[15]}, [r0,:128]!
vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
veor @XMM[8], @XMM[8], @T[0]
vst1.64 {@XMM[8]}, [r0,:128] @ next round tweak
vld1.8 {@XMM[6]-@XMM[7]}, [$inp]!
veor @XMM[5], @XMM[5], @XMM[13]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[6], @XMM[6], @XMM[14]
mov r5, $rounds @ pass rounds
veor @XMM[7], @XMM[7], @XMM[15]
mov r0, sp
bl _bsaes_encrypt8
vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
veor @XMM[1], @XMM[1], @XMM[ 9]
veor @XMM[8], @XMM[4], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
veor @XMM[9], @XMM[6], @XMM[11]
vld1.64 {@XMM[14]-@XMM[15]}, [r0,:128]!
veor @XMM[10], @XMM[3], @XMM[12]
vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
veor @XMM[11], @XMM[7], @XMM[13]
veor @XMM[12], @XMM[2], @XMM[14]
vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
veor @XMM[13], @XMM[5], @XMM[15]
vst1.8 {@XMM[12]-@XMM[13]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
subs $len, #0x80
bpl .Lxts_enc_loop
.Lxts_enc_short:
adds $len, #0x70
bmi .Lxts_enc_done
vldmia $magic, {$twmask} @ load XTS magic
vshr.s64 @T[0], @XMM[8], #63
mov r0, sp
vand @T[0], @T[0], $twmask
___
for($i=9;$i<16;$i++) {
$code.=<<___;
vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1]
vst1.64 {@XMM[$i-1]}, [r0,:128]!
vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
vshr.s64 @T[1], @XMM[$i], #63
veor @XMM[$i], @XMM[$i], @T[0]
vand @T[1], @T[1], $twmask
___
@T=reverse(@T);
$code.=<<___ if ($i>=10);
vld1.8 {@XMM[$i-10]}, [$inp]!
subs $len, #0x10
bmi .Lxts_enc_`$i-9`
___
$code.=<<___ if ($i>=11);
veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
___
}
$code.=<<___;
sub $len, #0x10
vst1.64 {@XMM[15]}, [r0,:128] @ next round tweak
vld1.8 {@XMM[6]}, [$inp]!
veor @XMM[5], @XMM[5], @XMM[13]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[6], @XMM[6], @XMM[14]
mov r5, $rounds @ pass rounds
mov r0, sp
bl _bsaes_encrypt8
vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
veor @XMM[1], @XMM[1], @XMM[ 9]
veor @XMM[8], @XMM[4], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
veor @XMM[9], @XMM[6], @XMM[11]
vld1.64 {@XMM[14]}, [r0,:128]!
veor @XMM[10], @XMM[3], @XMM[12]
vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
veor @XMM[11], @XMM[7], @XMM[13]
veor @XMM[12], @XMM[2], @XMM[14]
vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
vst1.8 {@XMM[12]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
b .Lxts_enc_done
.align 4
.Lxts_enc_6:
veor @XMM[4], @XMM[4], @XMM[12]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[5], @XMM[5], @XMM[13]
mov r5, $rounds @ pass rounds
mov r0, sp
bl _bsaes_encrypt8
vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
veor @XMM[1], @XMM[1], @XMM[ 9]
veor @XMM[8], @XMM[4], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
veor @XMM[9], @XMM[6], @XMM[11]
veor @XMM[10], @XMM[3], @XMM[12]
vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
veor @XMM[11], @XMM[7], @XMM[13]
vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
b .Lxts_enc_done
@ put this in range for both ARM and Thumb mode adr instructions
.align 5
.Lxts_magic:
.quad 1, 0x87
.align 5
.Lxts_enc_5:
veor @XMM[3], @XMM[3], @XMM[11]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[4], @XMM[4], @XMM[12]
mov r5, $rounds @ pass rounds
mov r0, sp
bl _bsaes_encrypt8
vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
vld1.64 {@XMM[12]}, [r0,:128]!
veor @XMM[1], @XMM[1], @XMM[ 9]
veor @XMM[8], @XMM[4], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
veor @XMM[9], @XMM[6], @XMM[11]
veor @XMM[10], @XMM[3], @XMM[12]
vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
vst1.8 {@XMM[10]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
b .Lxts_enc_done
.align 4
.Lxts_enc_4:
veor @XMM[2], @XMM[2], @XMM[10]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[3], @XMM[3], @XMM[11]
mov r5, $rounds @ pass rounds
mov r0, sp
bl _bsaes_encrypt8
vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
veor @XMM[1], @XMM[1], @XMM[ 9]
veor @XMM[8], @XMM[4], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
veor @XMM[9], @XMM[6], @XMM[11]
vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
b .Lxts_enc_done
.align 4
.Lxts_enc_3:
veor @XMM[1], @XMM[1], @XMM[9]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[2], @XMM[2], @XMM[10]
mov r5, $rounds @ pass rounds
mov r0, sp
bl _bsaes_encrypt8
vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]!
vld1.64 {@XMM[10]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
veor @XMM[1], @XMM[1], @XMM[ 9]
veor @XMM[8], @XMM[4], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
vst1.8 {@XMM[8]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
b .Lxts_enc_done
.align 4
.Lxts_enc_2:
veor @XMM[0], @XMM[0], @XMM[8]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[1], @XMM[1], @XMM[9]
mov r5, $rounds @ pass rounds
mov r0, sp
bl _bsaes_encrypt8
vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
veor @XMM[1], @XMM[1], @XMM[ 9]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
b .Lxts_enc_done
.align 4
.Lxts_enc_1:
mov r0, sp
veor @XMM[0], @XMM[0], @XMM[8]
mov r1, sp
vst1.8 {@XMM[0]}, [sp,:128]
mov r2, $key
mov r4, $fp @ preserve fp
bl AES_encrypt
vld1.8 {@XMM[0]}, [sp,:128]
veor @XMM[0], @XMM[0], @XMM[8]
vst1.8 {@XMM[0]}, [$out]!
mov $fp, r4
vmov @XMM[8], @XMM[9] @ next round tweak
.Lxts_enc_done:
#ifndef XTS_CHAIN_TWEAK
adds $len, #0x10
beq .Lxts_enc_ret
sub r6, $out, #0x10
.Lxts_enc_steal:
ldrb r0, [$inp], #1
ldrb r1, [$out, #-0x10]
strb r0, [$out, #-0x10]
strb r1, [$out], #1
subs $len, #1
bhi .Lxts_enc_steal
vld1.8 {@XMM[0]}, [r6]
mov r0, sp
veor @XMM[0], @XMM[0], @XMM[8]
mov r1, sp
vst1.8 {@XMM[0]}, [sp,:128]
mov r2, $key
mov r4, $fp @ preserve fp
bl AES_encrypt
vld1.8 {@XMM[0]}, [sp,:128]
veor @XMM[0], @XMM[0], @XMM[8]
vst1.8 {@XMM[0]}, [r6]
mov $fp, r4
#endif
.Lxts_enc_ret:
bic r0, $fp, #0xf
vmov.i32 q0, #0
vmov.i32 q1, #0
#ifdef XTS_CHAIN_TWEAK
ldr r1, [$fp, #0x20+VFP_ABI_FRAME] @ chain tweak
#endif
.Lxts_enc_bzero: @ wipe key schedule [if any]
vstmia sp!, {q0-q1}
cmp sp, r0
bne .Lxts_enc_bzero
mov sp, $fp
#ifdef XTS_CHAIN_TWEAK
vst1.8 {@XMM[8]}, [r1]
#endif
VFP_ABI_POP
ldmia sp!, {r4-r10, pc} @ return
.size ossl_bsaes_xts_encrypt,.-ossl_bsaes_xts_encrypt
.globl ossl_bsaes_xts_decrypt
.type ossl_bsaes_xts_decrypt,%function
.align 4
ossl_bsaes_xts_decrypt:
mov ip, sp
stmdb sp!, {r4-r10, lr} @ 0x20
VFP_ABI_PUSH
mov r6, sp @ future $fp
mov $inp, r0
mov $out, r1
mov $len, r2
mov $key, r3
sub r0, sp, #0x10 @ 0x10
bic r0, #0xf @ align at 16 bytes
mov sp, r0
#ifdef XTS_CHAIN_TWEAK
ldr r0, [ip] @ pointer to input tweak
#else
@ generate initial tweak
ldr r0, [ip, #4] @ iv[]
mov r1, sp
ldr r2, [ip, #0] @ key2
bl AES_encrypt
mov r0, sp @ pointer to initial tweak
#endif
ldr $rounds, [$key, #240] @ get # of rounds
mov $fp, r6
#ifndef BSAES_ASM_EXTENDED_KEY
@ allocate the key schedule on the stack
sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key
@ add r12, #`128-32` @ size of bit-sliced key schedule
sub r12, #`32+16` @ place for tweak[9]
@ populate the key schedule
mov r4, $key @ pass key
mov r5, $rounds @ pass # of rounds
mov sp, r12
add r12, #0x90 @ pass key schedule
bl _bsaes_key_convert
add r4, sp, #0x90
vldmia r4, {@XMM[6]}
vstmia r12, {@XMM[15]} @ save last round key
veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key
vstmia r4, {@XMM[7]}
#else
ldr r12, [$key, #244]
eors r12, #1
beq 0f
str r12, [$key, #244]
mov r4, $key @ pass key
mov r5, $rounds @ pass # of rounds
add r12, $key, #248 @ pass key schedule
bl _bsaes_key_convert
add r4, $key, #248
vldmia r4, {@XMM[6]}
vstmia r12, {@XMM[15]} @ save last round key
veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key
vstmia r4, {@XMM[7]}
.align 2
0: sub sp, #0x90 @ place for tweak[9]
#endif
vld1.8 {@XMM[8]}, [r0] @ initial tweak
adr $magic, .Lxts_magic
#ifndef XTS_CHAIN_TWEAK
tst $len, #0xf @ if not multiple of 16
it ne @ Thumb2 thing, sanity check in ARM
subne $len, #0x10 @ subtract another 16 bytes
#endif
subs $len, #0x80
blo .Lxts_dec_short
b .Lxts_dec_loop
.align 4
.Lxts_dec_loop:
vldmia $magic, {$twmask} @ load XTS magic
vshr.s64 @T[0], @XMM[8], #63
mov r0, sp
vand @T[0], @T[0], $twmask
___
for($i=9;$i<16;$i++) {
$code.=<<___;
vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1]
vst1.64 {@XMM[$i-1]}, [r0,:128]!
vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
vshr.s64 @T[1], @XMM[$i], #63
veor @XMM[$i], @XMM[$i], @T[0]
vand @T[1], @T[1], $twmask
___
@T=reverse(@T);
$code.=<<___ if ($i>=10);
vld1.8 {@XMM[$i-10]}, [$inp]!
___
$code.=<<___ if ($i>=11);
veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
___
}
$code.=<<___;
vadd.u64 @XMM[8], @XMM[15], @XMM[15]
vst1.64 {@XMM[15]}, [r0,:128]!
vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
veor @XMM[8], @XMM[8], @T[0]
vst1.64 {@XMM[8]}, [r0,:128] @ next round tweak
vld1.8 {@XMM[6]-@XMM[7]}, [$inp]!
veor @XMM[5], @XMM[5], @XMM[13]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[6], @XMM[6], @XMM[14]
mov r5, $rounds @ pass rounds
veor @XMM[7], @XMM[7], @XMM[15]
mov r0, sp
bl _bsaes_decrypt8
vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
veor @XMM[1], @XMM[1], @XMM[ 9]
veor @XMM[8], @XMM[6], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
veor @XMM[9], @XMM[4], @XMM[11]
vld1.64 {@XMM[14]-@XMM[15]}, [r0,:128]!
veor @XMM[10], @XMM[2], @XMM[12]
vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
veor @XMM[11], @XMM[7], @XMM[13]
veor @XMM[12], @XMM[3], @XMM[14]
vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
veor @XMM[13], @XMM[5], @XMM[15]
vst1.8 {@XMM[12]-@XMM[13]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
subs $len, #0x80
bpl .Lxts_dec_loop
.Lxts_dec_short:
adds $len, #0x70
bmi .Lxts_dec_done
vldmia $magic, {$twmask} @ load XTS magic
vshr.s64 @T[0], @XMM[8], #63
mov r0, sp
vand @T[0], @T[0], $twmask
___
for($i=9;$i<16;$i++) {
$code.=<<___;
vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1]
vst1.64 {@XMM[$i-1]}, [r0,:128]!
vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
vshr.s64 @T[1], @XMM[$i], #63
veor @XMM[$i], @XMM[$i], @T[0]
vand @T[1], @T[1], $twmask
___
@T=reverse(@T);
$code.=<<___ if ($i>=10);
vld1.8 {@XMM[$i-10]}, [$inp]!
subs $len, #0x10
bmi .Lxts_dec_`$i-9`
___
$code.=<<___ if ($i>=11);
veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
___
}
$code.=<<___;
sub $len, #0x10
vst1.64 {@XMM[15]}, [r0,:128] @ next round tweak
vld1.8 {@XMM[6]}, [$inp]!
veor @XMM[5], @XMM[5], @XMM[13]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[6], @XMM[6], @XMM[14]
mov r5, $rounds @ pass rounds
mov r0, sp
bl _bsaes_decrypt8
vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
veor @XMM[1], @XMM[1], @XMM[ 9]
veor @XMM[8], @XMM[6], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
veor @XMM[9], @XMM[4], @XMM[11]
vld1.64 {@XMM[14]}, [r0,:128]!
veor @XMM[10], @XMM[2], @XMM[12]
vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
veor @XMM[11], @XMM[7], @XMM[13]
veor @XMM[12], @XMM[3], @XMM[14]
vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
vst1.8 {@XMM[12]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
b .Lxts_dec_done
.align 4
.Lxts_dec_6:
vst1.64 {@XMM[14]}, [r0,:128] @ next round tweak
veor @XMM[4], @XMM[4], @XMM[12]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[5], @XMM[5], @XMM[13]
mov r5, $rounds @ pass rounds
mov r0, sp
bl _bsaes_decrypt8
vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
veor @XMM[1], @XMM[1], @XMM[ 9]
veor @XMM[8], @XMM[6], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
veor @XMM[9], @XMM[4], @XMM[11]
veor @XMM[10], @XMM[2], @XMM[12]
vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
veor @XMM[11], @XMM[7], @XMM[13]
vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
b .Lxts_dec_done
.align 4
.Lxts_dec_5:
veor @XMM[3], @XMM[3], @XMM[11]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[4], @XMM[4], @XMM[12]
mov r5, $rounds @ pass rounds
mov r0, sp
bl _bsaes_decrypt8
vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
vld1.64 {@XMM[12]}, [r0,:128]!
veor @XMM[1], @XMM[1], @XMM[ 9]
veor @XMM[8], @XMM[6], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
veor @XMM[9], @XMM[4], @XMM[11]
veor @XMM[10], @XMM[2], @XMM[12]
vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
vst1.8 {@XMM[10]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
b .Lxts_dec_done
.align 4
.Lxts_dec_4:
veor @XMM[2], @XMM[2], @XMM[10]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[3], @XMM[3], @XMM[11]
mov r5, $rounds @ pass rounds
mov r0, sp
bl _bsaes_decrypt8
vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
veor @XMM[1], @XMM[1], @XMM[ 9]
veor @XMM[8], @XMM[6], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
veor @XMM[9], @XMM[4], @XMM[11]
vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
b .Lxts_dec_done
.align 4
.Lxts_dec_3:
veor @XMM[1], @XMM[1], @XMM[9]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[2], @XMM[2], @XMM[10]
mov r5, $rounds @ pass rounds
mov r0, sp
bl _bsaes_decrypt8
vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]!
vld1.64 {@XMM[10]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
veor @XMM[1], @XMM[1], @XMM[ 9]
veor @XMM[8], @XMM[6], @XMM[10]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
vst1.8 {@XMM[8]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
b .Lxts_dec_done
.align 4
.Lxts_dec_2:
veor @XMM[0], @XMM[0], @XMM[8]
#ifndef BSAES_ASM_EXTENDED_KEY
add r4, sp, #0x90 @ pass key schedule
#else
add r4, $key, #248 @ pass key schedule
#endif
veor @XMM[1], @XMM[1], @XMM[9]
mov r5, $rounds @ pass rounds
mov r0, sp
bl _bsaes_decrypt8
vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]!
veor @XMM[0], @XMM[0], @XMM[ 8]
veor @XMM[1], @XMM[1], @XMM[ 9]
vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
b .Lxts_dec_done
.align 4
.Lxts_dec_1:
mov r0, sp
veor @XMM[0], @XMM[0], @XMM[8]
mov r1, sp
vst1.8 {@XMM[0]}, [sp,:128]
mov r5, $magic @ preserve magic
mov r2, $key
mov r4, $fp @ preserve fp
bl AES_decrypt
vld1.8 {@XMM[0]}, [sp,:128]
veor @XMM[0], @XMM[0], @XMM[8]
vst1.8 {@XMM[0]}, [$out]!
mov $fp, r4
mov $magic, r5
vmov @XMM[8], @XMM[9] @ next round tweak
.Lxts_dec_done:
#ifndef XTS_CHAIN_TWEAK
adds $len, #0x10
beq .Lxts_dec_ret
@ calculate one round of extra tweak for the stolen ciphertext
vldmia $magic, {$twmask}
vshr.s64 @XMM[6], @XMM[8], #63
vand @XMM[6], @XMM[6], $twmask
vadd.u64 @XMM[9], @XMM[8], @XMM[8]
vswp `&Dhi("@XMM[6]")`,`&Dlo("@XMM[6]")`
veor @XMM[9], @XMM[9], @XMM[6]
@ perform the final decryption with the last tweak value
vld1.8 {@XMM[0]}, [$inp]!
mov r0, sp
veor @XMM[0], @XMM[0], @XMM[9]
mov r1, sp
vst1.8 {@XMM[0]}, [sp,:128]
mov r2, $key
mov r4, $fp @ preserve fp
bl AES_decrypt
vld1.8 {@XMM[0]}, [sp,:128]
veor @XMM[0], @XMM[0], @XMM[9]
vst1.8 {@XMM[0]}, [$out]
mov r6, $out
.Lxts_dec_steal:
ldrb r1, [$out]
ldrb r0, [$inp], #1
strb r1, [$out, #0x10]
strb r0, [$out], #1
subs $len, #1
bhi .Lxts_dec_steal
vld1.8 {@XMM[0]}, [r6]
mov r0, sp
veor @XMM[0], @XMM[8]
mov r1, sp
vst1.8 {@XMM[0]}, [sp,:128]
mov r2, $key
bl AES_decrypt
vld1.8 {@XMM[0]}, [sp,:128]
veor @XMM[0], @XMM[0], @XMM[8]
vst1.8 {@XMM[0]}, [r6]
mov $fp, r4
#endif
.Lxts_dec_ret:
bic r0, $fp, #0xf
vmov.i32 q0, #0
vmov.i32 q1, #0
#ifdef XTS_CHAIN_TWEAK
ldr r1, [$fp, #0x20+VFP_ABI_FRAME] @ chain tweak
#endif
.Lxts_dec_bzero: @ wipe key schedule [if any]
vstmia sp!, {q0-q1}
cmp sp, r0
bne .Lxts_dec_bzero
mov sp, $fp
#ifdef XTS_CHAIN_TWEAK
vst1.8 {@XMM[8]}, [r1]
#endif
VFP_ABI_POP
ldmia sp!, {r4-r10, pc} @ return
.size ossl_bsaes_xts_decrypt,.-ossl_bsaes_xts_decrypt
___
}
$code.=<<___;
#endif
___
$code =~ s/\`([^\`]*)\`/eval($1)/gem;
open SELF,$0;
while(<SELF>) {
next if (/^#!/);
last if (!s/^#/@/ and !/^$/);
print;
}
close SELF;
print $code;
close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c
index 7c256493571e..4930d5022ee3 100644
--- a/crypto/asn1/a_bitstr.c
+++ b/crypto/asn1/a_bitstr.c
@@ -1,216 +1,222 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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)
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/asn1/asn1_parse.c b/crypto/asn1/asn1_parse.c
index 04d7ef66cfc9..6a4618d253d5 100644
--- a/crypto/asn1/asn1_parse.c
+++ b/crypto/asn1/asn1_parse.c
@@ -1,387 +1,387 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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/buffer.h>
#include <openssl/objects.h>
#include <openssl/asn1.h>
#ifndef ASN1_PARSE_MAXDEPTH
#define ASN1_PARSE_MAXDEPTH 128
#endif
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
int offset, int depth, int indent, int dump);
static int asn1_print_info(BIO *bp, long offset, int depth, int hl, long len,
int tag, int xclass, int constructed, int indent)
{
char str[128];
const char *p;
int pop_f_prefix = 0;
long saved_indent = -1;
int i = 0;
BIO *bio = NULL;
if (constructed & V_ASN1_CONSTRUCTED)
p = "cons: ";
else
p = "prim: ";
if (constructed != (V_ASN1_CONSTRUCTED | 1)) {
if (BIO_snprintf(str, sizeof(str), "%5ld:d=%-2d hl=%ld l=%4ld %s",
offset, depth, (long)hl, len, p) <= 0)
goto err;
} else {
if (BIO_snprintf(str, sizeof(str), "%5ld:d=%-2d hl=%ld l=inf %s",
offset, depth, (long)hl, p) <= 0)
goto err;
}
if (bp != NULL) {
if (BIO_set_prefix(bp, str) <= 0) {
if ((bio = BIO_new(BIO_f_prefix())) == NULL
|| (bp = BIO_push(bio, bp)) == NULL)
goto err;
pop_f_prefix = 1;
}
saved_indent = BIO_get_indent(bp);
- if (BIO_set_prefix(bp, str) <= 0 || BIO_set_indent(bp, indent) < 0)
+ if (BIO_set_prefix(bp, str) <= 0 || BIO_set_indent(bp, indent) <= 0)
goto err;
}
/*
* BIO_set_prefix made a copy of |str|, so we can safely use it for
* something else, ASN.1 tag printout.
*/
p = str;
if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
BIO_snprintf(str, sizeof(str), "priv [ %d ] ", tag);
else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
BIO_snprintf(str, sizeof(str), "cont [ %d ]", tag);
else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
BIO_snprintf(str, sizeof(str), "appl [ %d ]", tag);
else if (tag > 30)
BIO_snprintf(str, sizeof(str), "<ASN1 %d>", tag);
else
p = ASN1_tag2str(tag);
i = (BIO_printf(bp, "%-18s", p) > 0);
err:
if (saved_indent >= 0)
BIO_set_indent(bp, saved_indent);
if (pop_f_prefix)
BIO_pop(bp);
BIO_free(bio);
return i;
}
int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
{
return asn1_parse2(bp, &pp, len, 0, 0, indent, 0);
}
int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
int dump)
{
return asn1_parse2(bp, &pp, len, 0, 0, indent, dump);
}
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
int offset, int depth, int indent, int dump)
{
const unsigned char *p, *ep, *tot, *op, *opp;
long len;
int tag, xclass, ret = 0;
int nl, hl, j, r;
ASN1_OBJECT *o = NULL;
ASN1_OCTET_STRING *os = NULL;
ASN1_INTEGER *ai = NULL;
ASN1_ENUMERATED *ae = NULL;
/* ASN1_BMPSTRING *bmp=NULL; */
int dump_indent, dump_cont = 0;
if (depth > ASN1_PARSE_MAXDEPTH) {
BIO_puts(bp, "BAD RECURSION DEPTH\n");
return 0;
}
dump_indent = 6; /* Because we know BIO_dump_indent() */
p = *pp;
tot = p + length;
while (length > 0) {
op = p;
j = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (j & 0x80) {
BIO_puts(bp, "Error in encoding\n");
goto end;
}
hl = (p - op);
length -= hl;
/*
* if j == 0x21 it is a constructed indefinite length object
*/
if (!asn1_print_info(bp, (long)offset + (long)(op - *pp), depth,
hl, len, tag, xclass, j, (indent) ? depth : 0))
goto end;
if (j & V_ASN1_CONSTRUCTED) {
const unsigned char *sp = p;
ep = p + len;
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
if (len > length) {
BIO_printf(bp, "length is greater than %ld\n", length);
goto end;
}
if ((j == 0x21) && (len == 0)) {
for (;;) {
r = asn1_parse2(bp, &p, (long)(tot - p),
offset + (p - *pp), depth + 1,
indent, dump);
if (r == 0)
goto end;
if ((r == 2) || (p >= tot)) {
len = p - sp;
break;
}
}
} else {
long tmp = len;
while (p < ep) {
sp = p;
r = asn1_parse2(bp, &p, tmp,
offset + (p - *pp), depth + 1,
indent, dump);
if (r == 0)
goto end;
tmp -= p - sp;
}
}
} else if (xclass != 0) {
p += len;
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
} else {
nl = 0;
if ((tag == V_ASN1_PRINTABLESTRING) ||
(tag == V_ASN1_T61STRING) ||
(tag == V_ASN1_IA5STRING) ||
(tag == V_ASN1_VISIBLESTRING) ||
(tag == V_ASN1_NUMERICSTRING) ||
(tag == V_ASN1_UTF8STRING) ||
(tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) {
if (BIO_write(bp, ":", 1) <= 0)
goto end;
if ((len > 0) && BIO_write(bp, (const char *)p, (int)len)
!= (int)len)
goto end;
} else if (tag == V_ASN1_OBJECT) {
opp = op;
if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) {
if (BIO_write(bp, ":", 1) <= 0)
goto end;
i2a_ASN1_OBJECT(bp, o);
} else {
if (BIO_puts(bp, ":BAD OBJECT") <= 0)
goto end;
dump_cont = 1;
}
} else if (tag == V_ASN1_BOOLEAN) {
if (len != 1) {
if (BIO_puts(bp, ":BAD BOOLEAN") <= 0)
goto end;
dump_cont = 1;
}
if (len > 0)
BIO_printf(bp, ":%u", p[0]);
} else if (tag == V_ASN1_BMPSTRING) {
/* do the BMP thang */
} else if (tag == V_ASN1_OCTET_STRING) {
int i, printable = 1;
opp = op;
os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
if (os != NULL && os->length > 0) {
opp = os->data;
/*
* testing whether the octet string is printable
*/
for (i = 0; i < os->length; i++) {
if (((opp[i] < ' ') &&
(opp[i] != '\n') &&
(opp[i] != '\r') &&
(opp[i] != '\t')) || (opp[i] > '~')) {
printable = 0;
break;
}
}
if (printable)
/* printable string */
{
if (BIO_write(bp, ":", 1) <= 0)
goto end;
if (BIO_write(bp, (const char *)opp, os->length) <= 0)
goto end;
} else if (!dump)
/*
* not printable => print octet string as hex dump
*/
{
if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0)
goto end;
for (i = 0; i < os->length; i++) {
if (BIO_printf(bp, "%02X", opp[i]) <= 0)
goto end;
}
} else
/* print the normal dump */
{
if (!nl) {
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
}
if (BIO_dump_indent(bp,
(const char *)opp,
((dump == -1 || dump >
os->
length) ? os->length : dump),
dump_indent) <= 0)
goto end;
nl = 1;
}
}
ASN1_OCTET_STRING_free(os);
os = NULL;
} else if (tag == V_ASN1_INTEGER) {
int i;
opp = op;
ai = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
if (ai != NULL) {
if (BIO_write(bp, ":", 1) <= 0)
goto end;
if (ai->type == V_ASN1_NEG_INTEGER)
if (BIO_write(bp, "-", 1) <= 0)
goto end;
for (i = 0; i < ai->length; i++) {
if (BIO_printf(bp, "%02X", ai->data[i]) <= 0)
goto end;
}
if (ai->length == 0) {
if (BIO_write(bp, "00", 2) <= 0)
goto end;
}
} else {
if (BIO_puts(bp, ":BAD INTEGER") <= 0)
goto end;
dump_cont = 1;
}
ASN1_INTEGER_free(ai);
ai = NULL;
} else if (tag == V_ASN1_ENUMERATED) {
int i;
opp = op;
ae = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
if (ae != NULL) {
if (BIO_write(bp, ":", 1) <= 0)
goto end;
if (ae->type == V_ASN1_NEG_ENUMERATED)
if (BIO_write(bp, "-", 1) <= 0)
goto end;
for (i = 0; i < ae->length; i++) {
if (BIO_printf(bp, "%02X", ae->data[i]) <= 0)
goto end;
}
if (ae->length == 0) {
if (BIO_write(bp, "00", 2) <= 0)
goto end;
}
} else {
if (BIO_puts(bp, ":BAD ENUMERATED") <= 0)
goto end;
dump_cont = 1;
}
ASN1_ENUMERATED_free(ae);
ae = NULL;
} else if (len > 0 && dump) {
if (!nl) {
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
}
if (BIO_dump_indent(bp, (const char *)p,
((dump == -1 || dump > len) ? len : dump),
dump_indent) <= 0)
goto end;
nl = 1;
}
if (dump_cont) {
int i;
const unsigned char *tmp = op + hl;
if (BIO_puts(bp, ":[") <= 0)
goto end;
for (i = 0; i < len; i++) {
if (BIO_printf(bp, "%02X", tmp[i]) <= 0)
goto end;
}
if (BIO_puts(bp, "]") <= 0)
goto end;
dump_cont = 0;
}
if (!nl) {
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
}
p += len;
if ((tag == V_ASN1_EOC) && (xclass == 0)) {
ret = 2; /* End of sequence */
goto end;
}
}
length -= len;
}
ret = 1;
end:
ASN1_OBJECT_free(o);
ASN1_OCTET_STRING_free(os);
ASN1_INTEGER_free(ai);
ASN1_ENUMERATED_free(ae);
*pp = p;
return ret;
}
const char *ASN1_tag2str(int tag)
{
static const char *const tag2str[] = {
/* 0-4 */
"EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING",
/* 5-9 */
"NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL",
/* 10-13 */
"ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>",
/* 15-17 */
"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET",
/* 18-20 */
"NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
/* 21-24 */
"VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME",
/* 25-27 */
"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING",
/* 28-30 */
"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING"
};
if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
tag &= ~0x100;
if (tag < 0 || tag > 30)
return "(unknown)";
return tag2str[tag];
}
diff --git a/crypto/asn1/asn_pack.c b/crypto/asn1/asn_pack.c
index 292e6d817697..2389264f17da 100644
--- a/crypto/asn1/asn_pack.c
+++ b/crypto/asn1/asn_pack.c
@@ -1,62 +1,62 @@
/*
- * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-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/asn1.h>
/* ASN1 packing and unpacking functions */
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
{
ASN1_STRING *octmp;
if (oct == NULL || *oct == NULL) {
if ((octmp = ASN1_STRING_new()) == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else {
octmp = *oct;
}
OPENSSL_free(octmp->data);
octmp->data = NULL;
- if ((octmp->length = ASN1_item_i2d(obj, &octmp->data, it)) == 0) {
+ if ((octmp->length = ASN1_item_i2d(obj, &octmp->data, it)) <= 0) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_ENCODE_ERROR);
goto err;
}
if (octmp->data == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
if (oct != NULL && *oct == NULL)
*oct = octmp;
return octmp;
err:
if (oct == NULL || *oct == NULL)
ASN1_STRING_free(octmp);
return NULL;
}
/* Extract an ASN1 object from an ASN1_STRING */
void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it)
{
const unsigned char *p;
void *ret;
p = oct->data;
if ((ret = ASN1_item_d2i(NULL, &p, oct->length, it)) == NULL)
ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR);
return ret;
}
diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c
index ecc16a5ee36a..c86b9ac198ca 100644
--- a/crypto/bio/bio_lib.c
+++ b/crypto/bio/bio_lib.c
@@ -1,982 +1,982 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
#define OPENSSL_SUPPRESS_DEPRECATED
#include <stdio.h>
#include <errno.h>
#include <openssl/crypto.h>
#include "internal/numbers.h"
#include "bio_local.h"
/*
* Helper macro for the callback to determine whether an operator expects a
* len parameter or not
*/
#define HAS_LEN_OPER(o) ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE \
|| (o) == BIO_CB_GETS)
#ifndef OPENSSL_NO_DEPRECATED_3_0
# define HAS_CALLBACK(b) ((b)->callback != NULL || (b)->callback_ex != NULL)
#else
# define HAS_CALLBACK(b) ((b)->callback_ex != NULL)
#endif
/*
* Helper function to work out whether to call the new style callback or the old
* one, and translate between the two.
*
* This has a long return type for consistency with the old callback. Similarly
* for the "long" used for "inret"
*/
static long bio_call_callback(BIO *b, int oper, const char *argp, size_t len,
int argi, long argl, long inret,
size_t *processed)
{
long ret = inret;
#ifndef OPENSSL_NO_DEPRECATED_3_0
int bareoper;
if (b->callback_ex != NULL)
#endif
return b->callback_ex(b, oper, argp, len, argi, argl, inret, processed);
#ifndef OPENSSL_NO_DEPRECATED_3_0
/* Strip off any BIO_CB_RETURN flag */
bareoper = oper & ~BIO_CB_RETURN;
/*
* We have an old style callback, so we will have to do nasty casts and
* check for overflows.
*/
if (HAS_LEN_OPER(bareoper)) {
/* In this case |len| is set, and should be used instead of |argi| */
if (len > INT_MAX)
return -1;
argi = (int)len;
}
if (inret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
if (*processed > INT_MAX)
return -1;
inret = *processed;
}
ret = b->callback(b, oper, argp, argi, argl, inret);
if (ret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
*processed = (size_t)ret;
ret = 1;
}
#endif
return ret;
}
BIO *BIO_new_ex(OSSL_LIB_CTX *libctx, const BIO_METHOD *method)
{
BIO *bio = OPENSSL_zalloc(sizeof(*bio));
if (bio == NULL) {
ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return NULL;
}
bio->libctx = libctx;
bio->method = method;
bio->shutdown = 1;
bio->references = 1;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data))
goto err;
bio->lock = CRYPTO_THREAD_lock_new();
if (bio->lock == NULL) {
ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
goto err;
}
if (method->create != NULL && !method->create(bio)) {
ERR_raise(ERR_LIB_BIO, ERR_R_INIT_FAIL);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
CRYPTO_THREAD_lock_free(bio->lock);
goto err;
}
if (method->create == NULL)
bio->init = 1;
return bio;
err:
OPENSSL_free(bio);
return NULL;
}
BIO *BIO_new(const BIO_METHOD *method)
{
return BIO_new_ex(NULL, method);
}
int BIO_free(BIO *a)
{
int ret;
if (a == NULL)
return 0;
if (CRYPTO_DOWN_REF(&a->references, &ret, a->lock) <= 0)
return 0;
REF_PRINT_COUNT("BIO", a);
if (ret > 0)
return 1;
REF_ASSERT_ISNT(ret < 0);
if (HAS_CALLBACK(a)) {
ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL);
if (ret <= 0)
return 0;
}
if ((a->method != NULL) && (a->method->destroy != NULL))
a->method->destroy(a);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
CRYPTO_THREAD_lock_free(a->lock);
OPENSSL_free(a);
return 1;
}
void BIO_set_data(BIO *a, void *ptr)
{
a->ptr = ptr;
}
void *BIO_get_data(BIO *a)
{
return a->ptr;
}
void BIO_set_init(BIO *a, int init)
{
a->init = init;
}
int BIO_get_init(BIO *a)
{
return a->init;
}
void BIO_set_shutdown(BIO *a, int shut)
{
a->shutdown = shut;
}
int BIO_get_shutdown(BIO *a)
{
return a->shutdown;
}
void BIO_vfree(BIO *a)
{
BIO_free(a);
}
int BIO_up_ref(BIO *a)
{
int i;
if (CRYPTO_UP_REF(&a->references, &i, a->lock) <= 0)
return 0;
REF_PRINT_COUNT("BIO", a);
REF_ASSERT_ISNT(i < 2);
return i > 1;
}
void BIO_clear_flags(BIO *b, int flags)
{
b->flags &= ~flags;
}
int BIO_test_flags(const BIO *b, int flags)
{
return (b->flags & flags);
}
void BIO_set_flags(BIO *b, int flags)
{
b->flags |= flags;
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
BIO_callback_fn BIO_get_callback(const BIO *b)
{
return b->callback;
}
void BIO_set_callback(BIO *b, BIO_callback_fn cb)
{
b->callback = cb;
}
#endif
BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b)
{
return b->callback_ex;
}
void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb)
{
b->callback_ex = cb;
}
void BIO_set_callback_arg(BIO *b, char *arg)
{
b->cb_arg = arg;
}
char *BIO_get_callback_arg(const BIO *b)
{
return b->cb_arg;
}
const char *BIO_method_name(const BIO *b)
{
return b->method->name;
}
int BIO_method_type(const BIO *b)
{
return b->method->type;
}
/*
* This is essentially the same as BIO_read_ex() except that it allows
* 0 or a negative value to indicate failure (retryable or not) in the return.
* This is for compatibility with the old style BIO_read(), where existing code
* may make assumptions about the return value that it might get.
*/
static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes)
{
int ret;
if (b == NULL) {
ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
if (b->method == NULL || b->method->bread == NULL) {
ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (HAS_CALLBACK(b) &&
((ret = (int)bio_call_callback(b, BIO_CB_READ, data, dlen, 0, 0L, 1L,
NULL)) <= 0))
return ret;
if (!b->init) {
ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
return -1;
}
ret = b->method->bread(b, data, dlen, readbytes);
if (ret > 0)
b->num_read += (uint64_t)*readbytes;
if (HAS_CALLBACK(b))
ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, data,
dlen, 0, 0L, ret, readbytes);
/* Shouldn't happen */
if (ret > 0 && *readbytes > dlen) {
ERR_raise(ERR_LIB_BIO, ERR_R_INTERNAL_ERROR);
return -1;
}
return ret;
}
int BIO_read(BIO *b, void *data, int dlen)
{
size_t readbytes;
int ret;
if (dlen < 0)
return 0;
ret = bio_read_intern(b, data, (size_t)dlen, &readbytes);
if (ret > 0) {
/* *readbytes should always be <= dlen */
ret = (int)readbytes;
}
return ret;
}
int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes)
{
return bio_read_intern(b, data, dlen, readbytes) > 0;
}
static int bio_write_intern(BIO *b, const void *data, size_t dlen,
size_t *written)
{
size_t local_written;
int ret;
if (written != NULL)
*written = 0;
/*
* b == NULL is not an error but just means that zero bytes are written.
* Do not raise an error here.
*/
if (b == NULL)
return 0;
if (b->method == NULL || b->method->bwrite == NULL) {
ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (HAS_CALLBACK(b) &&
((ret = (int)bio_call_callback(b, BIO_CB_WRITE, data, dlen, 0, 0L, 1L,
NULL)) <= 0))
return ret;
if (!b->init) {
ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
return -1;
}
ret = b->method->bwrite(b, data, dlen, &local_written);
if (ret > 0)
b->num_write += (uint64_t)local_written;
if (HAS_CALLBACK(b))
ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, data,
dlen, 0, 0L, ret, &local_written);
if (written != NULL)
*written = local_written;
return ret;
}
int BIO_write(BIO *b, const void *data, int dlen)
{
size_t written;
int ret;
if (dlen <= 0)
return 0;
ret = bio_write_intern(b, data, (size_t)dlen, &written);
if (ret > 0) {
/* written should always be <= dlen */
ret = (int)written;
}
return ret;
}
int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written)
{
return bio_write_intern(b, data, dlen, written) > 0
|| (b != NULL && dlen == 0); /* order is important for *written */
}
int BIO_puts(BIO *b, const char *buf)
{
int ret;
size_t written = 0;
if (b == NULL) {
ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
if (b->method == NULL || b->method->bputs == NULL) {
ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (HAS_CALLBACK(b)) {
ret = (int)bio_call_callback(b, BIO_CB_PUTS, buf, 0, 0, 0L, 1L, NULL);
if (ret <= 0)
return ret;
}
if (!b->init) {
ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
return -1;
}
ret = b->method->bputs(b, buf);
if (ret > 0) {
b->num_write += (uint64_t)ret;
written = ret;
ret = 1;
}
if (HAS_CALLBACK(b))
ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, buf, 0, 0,
0L, ret, &written);
if (ret > 0) {
if (written > INT_MAX) {
ERR_raise(ERR_LIB_BIO, BIO_R_LENGTH_TOO_LONG);
ret = -1;
} else {
ret = (int)written;
}
}
return ret;
}
int BIO_gets(BIO *b, char *buf, int size)
{
int ret;
size_t readbytes = 0;
if (b == NULL) {
ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
if (b->method == NULL || b->method->bgets == NULL) {
ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (size < 0) {
ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
return -1;
}
if (HAS_CALLBACK(b)) {
ret = (int)bio_call_callback(b, BIO_CB_GETS, buf, size, 0, 0L, 1, NULL);
if (ret <= 0)
return ret;
}
if (!b->init) {
ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
return -1;
}
ret = b->method->bgets(b, buf, size);
if (ret > 0) {
readbytes = ret;
ret = 1;
}
if (HAS_CALLBACK(b))
ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, buf, size,
0, 0L, ret, &readbytes);
if (ret > 0) {
/* Shouldn't happen */
if (readbytes > (size_t)size)
ret = -1;
else
ret = (int)readbytes;
}
return ret;
}
int BIO_get_line(BIO *bio, char *buf, int size)
{
int ret = 0;
char *ptr = buf;
if (buf == NULL) {
ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
if (size <= 0) {
ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
return -1;
}
*buf = '\0';
if (bio == NULL) {
ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
if (!bio->init) {
ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
return -1;
}
while (size-- > 1 && (ret = BIO_read(bio, ptr, 1)) > 0)
if (*ptr++ == '\n')
break;
*ptr = '\0';
return ret > 0 || BIO_eof(bio) ? ptr - buf : ret;
}
int BIO_indent(BIO *b, int indent, int max)
{
if (indent < 0)
indent = 0;
if (indent > max)
indent = max;
while (indent--)
if (BIO_puts(b, " ") != 1)
return 0;
return 1;
}
long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
{
int i;
i = iarg;
return BIO_ctrl(b, cmd, larg, (char *)&i);
}
void *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
{
void *p = NULL;
if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0)
return NULL;
else
return p;
}
long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
{
long ret;
if (b == NULL)
return -1;
if (b->method == NULL || b->method->ctrl == NULL) {
ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (HAS_CALLBACK(b)) {
ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL);
if (ret <= 0)
return ret;
}
ret = b->method->ctrl(b, cmd, larg, parg);
if (HAS_CALLBACK(b))
ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd,
larg, ret, NULL);
return ret;
}
long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
long ret;
if (b == NULL)
return -2;
if (b->method == NULL || b->method->callback_ctrl == NULL
|| cmd != BIO_CTRL_SET_CALLBACK) {
ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (HAS_CALLBACK(b)) {
ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, cmd, 0, 1L,
NULL);
if (ret <= 0)
return ret;
}
ret = b->method->callback_ctrl(b, cmd, fp);
if (HAS_CALLBACK(b))
ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, 0,
cmd, 0, ret, NULL);
return ret;
}
/*
* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
* do; but those macros have inappropriate return type, and for interfacing
* from other programming languages, C macros aren't much of a help anyway.
*/
size_t BIO_ctrl_pending(BIO *bio)
{
long ret = BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
if (ret < 0)
ret = 0;
#if LONG_MAX > SIZE_MAX
if (ret > SIZE_MAX)
ret = SIZE_MAX;
#endif
return (size_t)ret;
}
size_t BIO_ctrl_wpending(BIO *bio)
{
long ret = BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
if (ret < 0)
ret = 0;
#if LONG_MAX > SIZE_MAX
if (ret > SIZE_MAX)
ret = SIZE_MAX;
#endif
return (size_t)ret;
}
/* put the 'bio' on the end of b's list of operators */
BIO *BIO_push(BIO *b, BIO *bio)
{
BIO *lb;
if (b == NULL)
return bio;
lb = b;
while (lb->next_bio != NULL)
lb = lb->next_bio;
lb->next_bio = bio;
if (bio != NULL)
bio->prev_bio = lb;
/* called to do internal processing */
BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb);
return b;
}
/* Remove the first and return the rest */
BIO *BIO_pop(BIO *b)
{
BIO *ret;
if (b == NULL)
return NULL;
ret = b->next_bio;
BIO_ctrl(b, BIO_CTRL_POP, 0, b);
if (b->prev_bio != NULL)
b->prev_bio->next_bio = b->next_bio;
if (b->next_bio != NULL)
b->next_bio->prev_bio = b->prev_bio;
b->next_bio = NULL;
b->prev_bio = NULL;
return ret;
}
BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
{
BIO *b, *last;
b = last = bio;
for (;;) {
if (!BIO_should_retry(b))
break;
last = b;
b = b->next_bio;
if (b == NULL)
break;
}
if (reason != NULL)
*reason = last->retry_reason;
return last;
}
int BIO_get_retry_reason(BIO *bio)
{
return bio->retry_reason;
}
void BIO_set_retry_reason(BIO *bio, int reason)
{
bio->retry_reason = reason;
}
BIO *BIO_find_type(BIO *bio, int type)
{
int mt, mask;
if (bio == NULL) {
ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
mask = type & 0xff;
do {
if (bio->method != NULL) {
mt = bio->method->type;
if (!mask) {
if (mt & type)
return bio;
} else if (mt == type) {
return bio;
}
}
bio = bio->next_bio;
} while (bio != NULL);
return NULL;
}
BIO *BIO_next(BIO *b)
{
if (b == NULL)
return NULL;
return b->next_bio;
}
void BIO_set_next(BIO *b, BIO *next)
{
b->next_bio = next;
}
void BIO_free_all(BIO *bio)
{
BIO *b;
int ref;
while (bio != NULL) {
b = bio;
ref = b->references;
bio = bio->next_bio;
BIO_free(b);
/* Since ref count > 1, don't free anyone else. */
if (ref > 1)
break;
}
}
BIO *BIO_dup_chain(BIO *in)
{
BIO *ret = NULL, *eoc = NULL, *bio, *new_bio;
for (bio = in; bio != NULL; bio = bio->next_bio) {
if ((new_bio = BIO_new(bio->method)) == NULL)
goto err;
#ifndef OPENSSL_NO_DEPRECATED_3_0
new_bio->callback = bio->callback;
#endif
new_bio->callback_ex = bio->callback_ex;
new_bio->cb_arg = bio->cb_arg;
new_bio->init = bio->init;
new_bio->shutdown = bio->shutdown;
new_bio->flags = bio->flags;
/* This will let SSL_s_sock() work with stdin/stdout */
new_bio->num = bio->num;
- if (!BIO_dup_state(bio, (char *)new_bio)) {
+ if (BIO_dup_state(bio, (char *)new_bio) <= 0) {
BIO_free(new_bio);
goto err;
}
/* copy app data */
if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data,
&bio->ex_data)) {
BIO_free(new_bio);
goto err;
}
if (ret == NULL) {
eoc = new_bio;
ret = eoc;
} else {
BIO_push(eoc, new_bio);
eoc = new_bio;
}
}
return ret;
err:
BIO_free_all(ret);
return NULL;
}
void BIO_copy_next_retry(BIO *b)
{
BIO_set_flags(b, BIO_get_retry_flags(b->next_bio));
b->retry_reason = b->next_bio->retry_reason;
}
int BIO_set_ex_data(BIO *bio, int idx, void *data)
{
return CRYPTO_set_ex_data(&(bio->ex_data), idx, data);
}
void *BIO_get_ex_data(const BIO *bio, int idx)
{
return CRYPTO_get_ex_data(&(bio->ex_data), idx);
}
uint64_t BIO_number_read(BIO *bio)
{
if (bio)
return bio->num_read;
return 0;
}
uint64_t BIO_number_written(BIO *bio)
{
if (bio)
return bio->num_write;
return 0;
}
void bio_free_ex_data(BIO *bio)
{
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
}
void bio_cleanup(void)
{
#ifndef OPENSSL_NO_SOCK
bio_sock_cleanup_int();
CRYPTO_THREAD_lock_free(bio_lookup_lock);
bio_lookup_lock = NULL;
#endif
CRYPTO_THREAD_lock_free(bio_type_lock);
bio_type_lock = NULL;
}
/* Internal variant of the below BIO_wait() not calling BIOerr() */
static int bio_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds)
{
#ifndef OPENSSL_NO_SOCK
int fd;
#endif
long sec_diff;
if (max_time == 0) /* no timeout */
return 1;
#ifndef OPENSSL_NO_SOCK
if (BIO_get_fd(bio, &fd) > 0 && fd < FD_SETSIZE)
return BIO_socket_wait(fd, BIO_should_read(bio), max_time);
#endif
/* fall back to polling since no sockets are available */
sec_diff = (long)(max_time - time(NULL)); /* might overflow */
if (sec_diff < 0)
return 0; /* clearly timeout */
/* now take a nap at most the given number of milliseconds */
if (sec_diff == 0) { /* we are below the 1 seconds resolution of max_time */
if (nap_milliseconds > 1000)
nap_milliseconds = 1000;
} else { /* for sec_diff > 0, take min(sec_diff * 1000, nap_milliseconds) */
if ((unsigned long)sec_diff * 1000 < nap_milliseconds)
nap_milliseconds = (unsigned int)sec_diff * 1000;
}
ossl_sleep(nap_milliseconds);
return 1;
}
/*-
* Wait on (typically socket-based) BIO at most until max_time.
* Succeed immediately if max_time == 0.
* If sockets are not available support polling: succeed after waiting at most
* the number of nap_milliseconds in order to avoid a tight busy loop.
* Call BIOerr(...) on timeout or error.
* Returns -1 on error, 0 on timeout, and 1 on success.
*/
int BIO_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds)
{
int rv = bio_wait(bio, max_time, nap_milliseconds);
if (rv <= 0)
ERR_raise(ERR_LIB_BIO,
rv == 0 ? BIO_R_TRANSFER_TIMEOUT : BIO_R_TRANSFER_ERROR);
return rv;
}
/*
* Connect via given BIO using BIO_do_connect() until success/timeout/error.
* Parameter timeout == 0 means no timeout, < 0 means exactly one try.
* For non-blocking and potentially even non-socket BIOs perform polling with
* the given density: between polls sleep nap_milliseconds using BIO_wait()
* in order to avoid a tight busy loop.
* Returns -1 on error, 0 on timeout, and 1 on success.
*/
int BIO_do_connect_retry(BIO *bio, int timeout, int nap_milliseconds)
{
int blocking = timeout <= 0;
time_t max_time = timeout > 0 ? time(NULL) + timeout : 0;
int rv;
if (bio == NULL) {
ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
if (nap_milliseconds < 0)
nap_milliseconds = 100;
BIO_set_nbio(bio, !blocking);
retry:
ERR_set_mark();
rv = BIO_do_connect(bio);
if (rv <= 0) { /* could be timeout or retryable error or fatal error */
int err = ERR_peek_last_error();
int reason = ERR_GET_REASON(err);
int do_retry = BIO_should_retry(bio); /* may be 1 only if !blocking */
if (ERR_GET_LIB(err) == ERR_LIB_BIO) {
switch (reason) {
case ERR_R_SYS_LIB:
/*
* likely retryable system error occurred, which may be
* EAGAIN (resource temporarily unavailable) some 40 secs after
* calling getaddrinfo(): Temporary failure in name resolution
* or a premature ETIMEDOUT, some 30 seconds after connect()
*/
case BIO_R_CONNECT_ERROR:
case BIO_R_NBIO_CONNECT_ERROR:
/* some likely retryable connection error occurred */
(void)BIO_reset(bio); /* often needed to avoid retry failure */
do_retry = 1;
break;
default:
break;
}
}
if (timeout >= 0 && do_retry) {
ERR_pop_to_mark();
/* will not actually wait if timeout == 0 (i.e., blocking BIO): */
rv = bio_wait(bio, max_time, nap_milliseconds);
if (rv > 0)
goto retry;
ERR_raise(ERR_LIB_BIO,
rv == 0 ? BIO_R_CONNECT_TIMEOUT : BIO_R_CONNECT_ERROR);
} else {
ERR_clear_last_mark();
rv = -1;
if (err == 0) /* missing error queue entry */
/* workaround: general error */
ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR);
}
} else {
ERR_clear_last_mark();
}
return rv;
}
diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c
index 1cda96733548..8870831039e9 100644
--- a/crypto/bio/bss_acpt.c
+++ b/crypto/bio/bss_acpt.c
@@ -1,575 +1,575 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
#define OPENSSL_SUPPRESS_DEPRECATED
#include <stdio.h>
#include <errno.h>
#include "bio_local.h"
#ifndef OPENSSL_NO_SOCK
typedef struct bio_accept_st {
int state;
int accept_family;
int bind_mode; /* Socket mode for BIO_listen */
int accepted_mode; /* Socket mode for BIO_accept (set on accepted sock) */
char *param_addr;
char *param_serv;
int accept_sock;
BIO_ADDRINFO *addr_first;
const BIO_ADDRINFO *addr_iter;
BIO_ADDR cache_accepting_addr; /* Useful if we asked for port 0 */
char *cache_accepting_name, *cache_accepting_serv;
BIO_ADDR cache_peer_addr;
char *cache_peer_name, *cache_peer_serv;
BIO *bio_chain;
} BIO_ACCEPT;
static int acpt_write(BIO *h, const char *buf, int num);
static int acpt_read(BIO *h, char *buf, int size);
static int acpt_puts(BIO *h, const char *str);
static long acpt_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int acpt_new(BIO *h);
static int acpt_free(BIO *data);
static int acpt_state(BIO *b, BIO_ACCEPT *c);
static void acpt_close_socket(BIO *data);
static BIO_ACCEPT *BIO_ACCEPT_new(void);
static void BIO_ACCEPT_free(BIO_ACCEPT *a);
# define ACPT_S_BEFORE 1
# define ACPT_S_GET_ADDR 2
# define ACPT_S_CREATE_SOCKET 3
# define ACPT_S_LISTEN 4
# define ACPT_S_ACCEPT 5
# define ACPT_S_OK 6
static const BIO_METHOD methods_acceptp = {
BIO_TYPE_ACCEPT,
"socket accept",
bwrite_conv,
acpt_write,
bread_conv,
acpt_read,
acpt_puts,
NULL, /* connect_gets, */
acpt_ctrl,
acpt_new,
acpt_free,
NULL, /* connect_callback_ctrl */
};
const BIO_METHOD *BIO_s_accept(void)
{
return &methods_acceptp;
}
static int acpt_new(BIO *bi)
{
BIO_ACCEPT *ba;
bi->init = 0;
bi->num = (int)INVALID_SOCKET;
bi->flags = 0;
if ((ba = BIO_ACCEPT_new()) == NULL)
return 0;
bi->ptr = (char *)ba;
ba->state = ACPT_S_BEFORE;
bi->shutdown = 1;
return 1;
}
static BIO_ACCEPT *BIO_ACCEPT_new(void)
{
BIO_ACCEPT *ret;
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->accept_family = BIO_FAMILY_IPANY;
ret->accept_sock = (int)INVALID_SOCKET;
return ret;
}
static void BIO_ACCEPT_free(BIO_ACCEPT *a)
{
if (a == NULL)
return;
OPENSSL_free(a->param_addr);
OPENSSL_free(a->param_serv);
BIO_ADDRINFO_free(a->addr_first);
OPENSSL_free(a->cache_accepting_name);
OPENSSL_free(a->cache_accepting_serv);
OPENSSL_free(a->cache_peer_name);
OPENSSL_free(a->cache_peer_serv);
BIO_free(a->bio_chain);
OPENSSL_free(a);
}
static void acpt_close_socket(BIO *bio)
{
BIO_ACCEPT *c;
c = (BIO_ACCEPT *)bio->ptr;
if (c->accept_sock != (int)INVALID_SOCKET) {
shutdown(c->accept_sock, 2);
closesocket(c->accept_sock);
c->accept_sock = (int)INVALID_SOCKET;
bio->num = (int)INVALID_SOCKET;
}
}
static int acpt_free(BIO *a)
{
BIO_ACCEPT *data;
if (a == NULL)
return 0;
data = (BIO_ACCEPT *)a->ptr;
if (a->shutdown) {
acpt_close_socket(a);
BIO_ACCEPT_free(data);
a->ptr = NULL;
a->flags = 0;
a->init = 0;
}
return 1;
}
static int acpt_state(BIO *b, BIO_ACCEPT *c)
{
BIO *bio = NULL, *dbio;
int s = -1, ret = -1;
for (;;) {
switch (c->state) {
case ACPT_S_BEFORE:
if (c->param_addr == NULL && c->param_serv == NULL) {
ERR_raise_data(ERR_LIB_BIO,
BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED,
"hostname=%s, service=%s",
c->param_addr, c->param_serv);
goto exit_loop;
}
/* Because we're starting a new bind, any cached name and serv
* are now obsolete and need to be cleaned out.
* QUESTION: should this be done in acpt_close_socket() instead?
*/
OPENSSL_free(c->cache_accepting_name);
c->cache_accepting_name = NULL;
OPENSSL_free(c->cache_accepting_serv);
c->cache_accepting_serv = NULL;
OPENSSL_free(c->cache_peer_name);
c->cache_peer_name = NULL;
OPENSSL_free(c->cache_peer_serv);
c->cache_peer_serv = NULL;
c->state = ACPT_S_GET_ADDR;
break;
case ACPT_S_GET_ADDR:
{
int family = AF_UNSPEC;
switch (c->accept_family) {
case BIO_FAMILY_IPV6:
if (1) { /* This is a trick we use to avoid bit rot.
* at least the "else" part will always be
* compiled.
*/
#ifdef AF_INET6
family = AF_INET6;
} else {
#endif
ERR_raise(ERR_LIB_BIO, BIO_R_UNAVAILABLE_IP_FAMILY);
goto exit_loop;
}
break;
case BIO_FAMILY_IPV4:
family = AF_INET;
break;
case BIO_FAMILY_IPANY:
family = AF_UNSPEC;
break;
default:
ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_IP_FAMILY);
goto exit_loop;
}
if (BIO_lookup(c->param_addr, c->param_serv, BIO_LOOKUP_SERVER,
family, SOCK_STREAM, &c->addr_first) == 0)
goto exit_loop;
}
if (c->addr_first == NULL) {
ERR_raise(ERR_LIB_BIO, BIO_R_LOOKUP_RETURNED_NOTHING);
goto exit_loop;
}
c->addr_iter = c->addr_first;
c->state = ACPT_S_CREATE_SOCKET;
break;
case ACPT_S_CREATE_SOCKET:
ERR_set_mark();
s = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
BIO_ADDRINFO_socktype(c->addr_iter),
BIO_ADDRINFO_protocol(c->addr_iter), 0);
if (s == (int)INVALID_SOCKET) {
if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter)) != NULL) {
/*
* if there are more addresses to try, do that first
*/
ERR_pop_to_mark();
break;
}
ERR_clear_last_mark();
ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
"calling socket(%s, %s)",
c->param_addr, c->param_serv);
ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
goto exit_loop;
}
c->accept_sock = s;
b->num = s;
c->state = ACPT_S_LISTEN;
s = -1;
break;
case ACPT_S_LISTEN:
{
if (!BIO_listen(c->accept_sock,
BIO_ADDRINFO_address(c->addr_iter),
c->bind_mode)) {
BIO_closesocket(c->accept_sock);
goto exit_loop;
}
}
{
union BIO_sock_info_u info;
info.addr = &c->cache_accepting_addr;
if (!BIO_sock_info(c->accept_sock, BIO_SOCK_INFO_ADDRESS,
&info)) {
BIO_closesocket(c->accept_sock);
goto exit_loop;
}
}
c->cache_accepting_name =
BIO_ADDR_hostname_string(&c->cache_accepting_addr, 1);
c->cache_accepting_serv =
BIO_ADDR_service_string(&c->cache_accepting_addr, 1);
c->state = ACPT_S_ACCEPT;
s = -1;
ret = 1;
goto end;
case ACPT_S_ACCEPT:
if (b->next_bio != NULL) {
c->state = ACPT_S_OK;
break;
}
BIO_clear_retry_flags(b);
b->retry_reason = 0;
OPENSSL_free(c->cache_peer_name);
c->cache_peer_name = NULL;
OPENSSL_free(c->cache_peer_serv);
c->cache_peer_serv = NULL;
s = BIO_accept_ex(c->accept_sock, &c->cache_peer_addr,
c->accepted_mode);
/* If the returned socket is invalid, this might still be
* retryable
*/
if (s < 0) {
if (BIO_sock_should_retry(s)) {
BIO_set_retry_special(b);
b->retry_reason = BIO_RR_ACCEPT;
goto end;
}
}
/* If it wasn't retryable, we fail */
if (s < 0) {
ret = s;
goto exit_loop;
}
bio = BIO_new_socket(s, BIO_CLOSE);
if (bio == NULL)
goto exit_loop;
BIO_set_callback_ex(bio, BIO_get_callback_ex(b));
#ifndef OPENSSL_NO_DEPRECATED_3_0
BIO_set_callback(bio, BIO_get_callback(b));
#endif
BIO_set_callback_arg(bio, BIO_get_callback_arg(b));
/*
* If the accept BIO has an bio_chain, we dup it and put the new
* socket at the end.
*/
if (c->bio_chain != NULL) {
if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL)
goto exit_loop;
if (!BIO_push(dbio, bio))
goto exit_loop;
bio = dbio;
}
if (BIO_push(b, bio) == NULL)
goto exit_loop;
c->cache_peer_name =
BIO_ADDR_hostname_string(&c->cache_peer_addr, 1);
c->cache_peer_serv =
BIO_ADDR_service_string(&c->cache_peer_addr, 1);
c->state = ACPT_S_OK;
bio = NULL;
ret = 1;
goto end;
case ACPT_S_OK:
if (b->next_bio == NULL) {
c->state = ACPT_S_ACCEPT;
break;
}
ret = 1;
goto end;
default:
ret = 0;
goto end;
}
}
exit_loop:
if (bio != NULL)
BIO_free(bio);
else if (s >= 0)
BIO_closesocket(s);
end:
return ret;
}
static int acpt_read(BIO *b, char *out, int outl)
{
int ret = 0;
BIO_ACCEPT *data;
BIO_clear_retry_flags(b);
data = (BIO_ACCEPT *)b->ptr;
while (b->next_bio == NULL) {
ret = acpt_state(b, data);
if (ret <= 0)
return ret;
}
ret = BIO_read(b->next_bio, out, outl);
BIO_copy_next_retry(b);
return ret;
}
static int acpt_write(BIO *b, const char *in, int inl)
{
int ret;
BIO_ACCEPT *data;
BIO_clear_retry_flags(b);
data = (BIO_ACCEPT *)b->ptr;
while (b->next_bio == NULL) {
ret = acpt_state(b, data);
if (ret <= 0)
return ret;
}
ret = BIO_write(b->next_bio, in, inl);
BIO_copy_next_retry(b);
return ret;
}
static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr)
{
int *ip;
long ret = 1;
BIO_ACCEPT *data;
char **pp;
data = (BIO_ACCEPT *)b->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
ret = 0;
data->state = ACPT_S_BEFORE;
acpt_close_socket(b);
BIO_ADDRINFO_free(data->addr_first);
data->addr_first = NULL;
b->flags = 0;
break;
case BIO_C_DO_STATE_MACHINE:
/* use this one to start the connection */
ret = (long)acpt_state(b, data);
break;
case BIO_C_SET_ACCEPT:
if (ptr != NULL) {
if (num == 0) {
char *hold_serv = data->param_serv;
/* We affect the hostname regardless. However, the input
* string might contain a host:service spec, so we must
* parse it, which might or might not affect the service
*/
OPENSSL_free(data->param_addr);
data->param_addr = NULL;
ret = BIO_parse_hostserv(ptr,
&data->param_addr,
&data->param_serv,
BIO_PARSE_PRIO_SERV);
if (hold_serv != data->param_serv)
OPENSSL_free(hold_serv);
b->init = 1;
} else if (num == 1) {
OPENSSL_free(data->param_serv);
if ((data->param_serv = OPENSSL_strdup(ptr)) == NULL)
ret = 0;
else
b->init = 1;
} else if (num == 2) {
data->bind_mode |= BIO_SOCK_NONBLOCK;
} else if (num == 3) {
BIO_free(data->bio_chain);
data->bio_chain = (BIO *)ptr;
} else if (num == 4) {
data->accept_family = *(int *)ptr;
}
} else {
if (num == 2) {
data->bind_mode &= ~BIO_SOCK_NONBLOCK;
}
}
break;
case BIO_C_SET_NBIO:
if (num != 0)
data->accepted_mode |= BIO_SOCK_NONBLOCK;
else
data->accepted_mode &= ~BIO_SOCK_NONBLOCK;
break;
case BIO_C_SET_FD:
b->num = *((int *)ptr);
data->accept_sock = b->num;
data->state = ACPT_S_ACCEPT;
b->shutdown = (int)num;
b->init = 1;
break;
case BIO_C_GET_FD:
if (b->init) {
ip = (int *)ptr;
if (ip != NULL)
*ip = data->accept_sock;
ret = data->accept_sock;
} else
ret = -1;
break;
case BIO_C_GET_ACCEPT:
if (b->init) {
if (num == 0 && ptr != NULL) {
pp = (char **)ptr;
*pp = data->cache_accepting_name;
} else if (num == 1 && ptr != NULL) {
pp = (char **)ptr;
*pp = data->cache_accepting_serv;
} else if (num == 2 && ptr != NULL) {
pp = (char **)ptr;
*pp = data->cache_peer_name;
} else if (num == 3 && ptr != NULL) {
pp = (char **)ptr;
*pp = data->cache_peer_serv;
} else if (num == 4) {
switch (BIO_ADDRINFO_family(data->addr_iter)) {
#ifdef AF_INET6
case AF_INET6:
ret = BIO_FAMILY_IPV6;
break;
#endif
case AF_INET:
ret = BIO_FAMILY_IPV4;
break;
case 0:
ret = data->accept_family;
break;
default:
ret = -1;
break;
}
} else
ret = -1;
} else
ret = -1;
break;
case BIO_CTRL_GET_CLOSE:
ret = b->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
b->shutdown = (int)num;
break;
case BIO_CTRL_PENDING:
case BIO_CTRL_WPENDING:
ret = 0;
break;
case BIO_CTRL_FLUSH:
break;
case BIO_C_SET_BIND_MODE:
data->bind_mode = (int)num;
break;
case BIO_C_GET_BIND_MODE:
ret = (long)data->bind_mode;
break;
case BIO_CTRL_DUP:
break;
case BIO_CTRL_EOF:
if (b->next_bio == NULL)
ret = 0;
else
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
break;
default:
ret = 0;
break;
}
return ret;
}
static int acpt_puts(BIO *bp, const char *str)
{
int n, ret;
n = strlen(str);
ret = acpt_write(bp, str, n);
return ret;
}
BIO *BIO_new_accept(const char *str)
{
BIO *ret;
ret = BIO_new(BIO_s_accept());
if (ret == NULL)
return NULL;
- if (BIO_set_accept_name(ret, str))
+ if (BIO_set_accept_name(ret, str) > 0)
return ret;
BIO_free(ret);
return NULL;
}
#endif
diff --git a/crypto/bn/bn_asm.c b/crypto/bn/bn_asm.c
index 257701d9dc7c..4ffe443066cc 100644
--- a/crypto/bn/bn_asm.c
+++ b/crypto/bn/bn_asm.c
@@ -1,1039 +1,1049 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <assert.h>
#include <openssl/crypto.h>
#include "internal/cryptlib.h"
#include "bn_local.h"
#if defined(BN_LLONG) || defined(BN_UMULT_HIGH)
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
BN_ULONG w)
{
BN_ULONG c1 = 0;
assert(num >= 0);
if (num <= 0)
return c1;
# ifndef OPENSSL_SMALL_FOOTPRINT
while (num & ~3) {
mul_add(rp[0], ap[0], w, c1);
mul_add(rp[1], ap[1], w, c1);
mul_add(rp[2], ap[2], w, c1);
mul_add(rp[3], ap[3], w, c1);
ap += 4;
rp += 4;
num -= 4;
}
# endif
while (num) {
mul_add(rp[0], ap[0], w, c1);
ap++;
rp++;
num--;
}
return c1;
}
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
{
BN_ULONG c1 = 0;
assert(num >= 0);
if (num <= 0)
return c1;
# ifndef OPENSSL_SMALL_FOOTPRINT
while (num & ~3) {
mul(rp[0], ap[0], w, c1);
mul(rp[1], ap[1], w, c1);
mul(rp[2], ap[2], w, c1);
mul(rp[3], ap[3], w, c1);
ap += 4;
rp += 4;
num -= 4;
}
# endif
while (num) {
mul(rp[0], ap[0], w, c1);
ap++;
rp++;
num--;
}
return c1;
}
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
{
assert(n >= 0);
if (n <= 0)
return;
# ifndef OPENSSL_SMALL_FOOTPRINT
while (n & ~3) {
sqr(r[0], r[1], a[0]);
sqr(r[2], r[3], a[1]);
sqr(r[4], r[5], a[2]);
sqr(r[6], r[7], a[3]);
a += 4;
r += 8;
n -= 4;
}
# endif
while (n) {
sqr(r[0], r[1], a[0]);
a++;
r += 2;
n--;
}
}
#else /* !(defined(BN_LLONG) ||
* defined(BN_UMULT_HIGH)) */
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
BN_ULONG w)
{
BN_ULONG c = 0;
BN_ULONG bl, bh;
assert(num >= 0);
if (num <= 0)
return (BN_ULONG)0;
bl = LBITS(w);
bh = HBITS(w);
# ifndef OPENSSL_SMALL_FOOTPRINT
while (num & ~3) {
mul_add(rp[0], ap[0], bl, bh, c);
mul_add(rp[1], ap[1], bl, bh, c);
mul_add(rp[2], ap[2], bl, bh, c);
mul_add(rp[3], ap[3], bl, bh, c);
ap += 4;
rp += 4;
num -= 4;
}
# endif
while (num) {
mul_add(rp[0], ap[0], bl, bh, c);
ap++;
rp++;
num--;
}
return c;
}
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
{
BN_ULONG carry = 0;
BN_ULONG bl, bh;
assert(num >= 0);
if (num <= 0)
return (BN_ULONG)0;
bl = LBITS(w);
bh = HBITS(w);
# ifndef OPENSSL_SMALL_FOOTPRINT
while (num & ~3) {
mul(rp[0], ap[0], bl, bh, carry);
mul(rp[1], ap[1], bl, bh, carry);
mul(rp[2], ap[2], bl, bh, carry);
mul(rp[3], ap[3], bl, bh, carry);
ap += 4;
rp += 4;
num -= 4;
}
# endif
while (num) {
mul(rp[0], ap[0], bl, bh, carry);
ap++;
rp++;
num--;
}
return carry;
}
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
{
assert(n >= 0);
if (n <= 0)
return;
# ifndef OPENSSL_SMALL_FOOTPRINT
while (n & ~3) {
sqr64(r[0], r[1], a[0]);
sqr64(r[2], r[3], a[1]);
sqr64(r[4], r[5], a[2]);
sqr64(r[6], r[7], a[3]);
a += 4;
r += 8;
n -= 4;
}
# endif
while (n) {
sqr64(r[0], r[1], a[0]);
a++;
r += 2;
n--;
}
}
#endif /* !(defined(BN_LLONG) ||
* defined(BN_UMULT_HIGH)) */
#if defined(BN_LLONG) && defined(BN_DIV2W)
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
{
return ((BN_ULONG)(((((BN_ULLONG) h) << BN_BITS2) | l) / (BN_ULLONG) d));
}
#else
/* Divide h,l by d and return the result. */
/* I need to test this some more :-( */
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
{
BN_ULONG dh, dl, q, ret = 0, th, tl, t;
int i, count = 2;
if (d == 0)
return BN_MASK2;
i = BN_num_bits_word(d);
assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
i = BN_BITS2 - i;
if (h >= d)
h -= d;
if (i) {
d <<= i;
h = (h << i) | (l >> (BN_BITS2 - i));
l <<= i;
}
dh = (d & BN_MASK2h) >> BN_BITS4;
dl = (d & BN_MASK2l);
for (;;) {
if ((h >> BN_BITS4) == dh)
q = BN_MASK2l;
else
q = h / dh;
th = q * dh;
tl = dl * q;
for (;;) {
t = h - th;
if ((t & BN_MASK2h) ||
((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4))))
break;
q--;
th -= dh;
tl -= dl;
}
t = (tl >> BN_BITS4);
tl = (tl << BN_BITS4) & BN_MASK2h;
th += t;
if (l < tl)
th++;
l -= tl;
if (h < th) {
h += d;
q--;
}
h -= th;
if (--count == 0)
break;
ret = q << BN_BITS4;
h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
l = (l & BN_MASK2l) << BN_BITS4;
}
ret |= q;
return ret;
}
#endif /* !defined(BN_LLONG) && defined(BN_DIV2W) */
#ifdef BN_LLONG
BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
int n)
{
BN_ULLONG ll = 0;
assert(n >= 0);
if (n <= 0)
return (BN_ULONG)0;
# ifndef OPENSSL_SMALL_FOOTPRINT
while (n & ~3) {
ll += (BN_ULLONG) a[0] + b[0];
r[0] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
ll += (BN_ULLONG) a[1] + b[1];
r[1] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
ll += (BN_ULLONG) a[2] + b[2];
r[2] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
ll += (BN_ULLONG) a[3] + b[3];
r[3] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
a += 4;
b += 4;
r += 4;
n -= 4;
}
# endif
while (n) {
ll += (BN_ULLONG) a[0] + b[0];
r[0] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
a++;
b++;
r++;
n--;
}
return (BN_ULONG)ll;
}
#else /* !BN_LLONG */
BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
int n)
{
BN_ULONG c, l, t;
assert(n >= 0);
if (n <= 0)
return (BN_ULONG)0;
c = 0;
# ifndef OPENSSL_SMALL_FOOTPRINT
while (n & ~3) {
t = a[0];
t = (t + c) & BN_MASK2;
c = (t < c);
l = (t + b[0]) & BN_MASK2;
c += (l < t);
r[0] = l;
t = a[1];
t = (t + c) & BN_MASK2;
c = (t < c);
l = (t + b[1]) & BN_MASK2;
c += (l < t);
r[1] = l;
t = a[2];
t = (t + c) & BN_MASK2;
c = (t < c);
l = (t + b[2]) & BN_MASK2;
c += (l < t);
r[2] = l;
t = a[3];
t = (t + c) & BN_MASK2;
c = (t < c);
l = (t + b[3]) & BN_MASK2;
c += (l < t);
r[3] = l;
a += 4;
b += 4;
r += 4;
n -= 4;
}
# endif
while (n) {
t = a[0];
t = (t + c) & BN_MASK2;
c = (t < c);
l = (t + b[0]) & BN_MASK2;
c += (l < t);
r[0] = l;
a++;
b++;
r++;
n--;
}
return (BN_ULONG)c;
}
#endif /* !BN_LLONG */
BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
int n)
{
BN_ULONG t1, t2;
int c = 0;
assert(n >= 0);
if (n <= 0)
return (BN_ULONG)0;
#ifndef OPENSSL_SMALL_FOOTPRINT
while (n & ~3) {
t1 = a[0];
- t2 = b[0];
- r[0] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
- c = (t1 < t2);
+ t2 = (t1 - c) & BN_MASK2;
+ c = (t2 > t1);
+ t1 = b[0];
+ t1 = (t2 - t1) & BN_MASK2;
+ r[0] = t1;
+ c += (t1 > t2);
t1 = a[1];
- t2 = b[1];
- r[1] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
- c = (t1 < t2);
+ t2 = (t1 - c) & BN_MASK2;
+ c = (t2 > t1);
+ t1 = b[1];
+ t1 = (t2 - t1) & BN_MASK2;
+ r[1] = t1;
+ c += (t1 > t2);
t1 = a[2];
- t2 = b[2];
- r[2] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
- c = (t1 < t2);
+ t2 = (t1 - c) & BN_MASK2;
+ c = (t2 > t1);
+ t1 = b[2];
+ t1 = (t2 - t1) & BN_MASK2;
+ r[2] = t1;
+ c += (t1 > t2);
t1 = a[3];
- t2 = b[3];
- r[3] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
- c = (t1 < t2);
+ t2 = (t1 - c) & BN_MASK2;
+ c = (t2 > t1);
+ t1 = b[3];
+ t1 = (t2 - t1) & BN_MASK2;
+ r[3] = t1;
+ c += (t1 > t2);
a += 4;
b += 4;
r += 4;
n -= 4;
}
#endif
while (n) {
t1 = a[0];
- t2 = b[0];
- r[0] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
- c = (t1 < t2);
+ t2 = (t1 - c) & BN_MASK2;
+ c = (t2 > t1);
+ t1 = b[0];
+ t1 = (t2 - t1) & BN_MASK2;
+ r[0] = t1;
+ c += (t1 > t2);
a++;
b++;
r++;
n--;
}
return c;
}
#if defined(BN_MUL_COMBA) && !defined(OPENSSL_SMALL_FOOTPRINT)
# undef bn_mul_comba8
# undef bn_mul_comba4
# undef bn_sqr_comba8
# undef bn_sqr_comba4
/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */
/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
/*
* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number
* c=(c2,c1,c0)
*/
# ifdef BN_LLONG
/*
* Keep in mind that additions to multiplication result can not
* overflow, because its high half cannot be all-ones.
*/
# define mul_add_c(a,b,c0,c1,c2) do { \
BN_ULONG hi; \
BN_ULLONG t = (BN_ULLONG)(a)*(b); \
t += c0; /* no carry */ \
c0 = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
} while(0)
# define mul_add_c2(a,b,c0,c1,c2) do { \
BN_ULONG hi; \
BN_ULLONG t = (BN_ULLONG)(a)*(b); \
BN_ULLONG tt = t+c0; /* no carry */ \
c0 = (BN_ULONG)Lw(tt); \
hi = (BN_ULONG)Hw(tt); \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
t += c0; /* no carry */ \
c0 = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
} while(0)
# define sqr_add_c(a,i,c0,c1,c2) do { \
BN_ULONG hi; \
BN_ULLONG t = (BN_ULLONG)a[i]*a[i]; \
t += c0; /* no carry */ \
c0 = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
} while(0)
# define sqr_add_c2(a,i,j,c0,c1,c2) \
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
# elif defined(BN_UMULT_LOHI)
/*
* Keep in mind that additions to hi can not overflow, because
* the high word of a multiplication result cannot be all-ones.
*/
# define mul_add_c(a,b,c0,c1,c2) do { \
BN_ULONG ta = (a), tb = (b); \
BN_ULONG lo, hi; \
BN_UMULT_LOHI(lo,hi,ta,tb); \
- c0 += lo; hi += (c0<lo)?1:0; \
- c1 += hi; c2 += (c1<hi)?1:0; \
+ c0 += lo; hi += (c0<lo); \
+ c1 += hi; c2 += (c1<hi); \
} while(0)
# define mul_add_c2(a,b,c0,c1,c2) do { \
BN_ULONG ta = (a), tb = (b); \
BN_ULONG lo, hi, tt; \
BN_UMULT_LOHI(lo,hi,ta,tb); \
- c0 += lo; tt = hi+((c0<lo)?1:0); \
- c1 += tt; c2 += (c1<tt)?1:0; \
- c0 += lo; hi += (c0<lo)?1:0; \
- c1 += hi; c2 += (c1<hi)?1:0; \
+ c0 += lo; tt = hi + (c0<lo); \
+ c1 += tt; c2 += (c1<tt); \
+ c0 += lo; hi += (c0<lo); \
+ c1 += hi; c2 += (c1<hi); \
} while(0)
# define sqr_add_c(a,i,c0,c1,c2) do { \
BN_ULONG ta = (a)[i]; \
BN_ULONG lo, hi; \
BN_UMULT_LOHI(lo,hi,ta,ta); \
- c0 += lo; hi += (c0<lo)?1:0; \
- c1 += hi; c2 += (c1<hi)?1:0; \
+ c0 += lo; hi += (c0<lo); \
+ c1 += hi; c2 += (c1<hi); \
} while(0)
# define sqr_add_c2(a,i,j,c0,c1,c2) \
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
# elif defined(BN_UMULT_HIGH)
/*
* Keep in mind that additions to hi can not overflow, because
* the high word of a multiplication result cannot be all-ones.
*/
# define mul_add_c(a,b,c0,c1,c2) do { \
BN_ULONG ta = (a), tb = (b); \
BN_ULONG lo = ta * tb; \
BN_ULONG hi = BN_UMULT_HIGH(ta,tb); \
- c0 += lo; hi += (c0<lo)?1:0; \
- c1 += hi; c2 += (c1<hi)?1:0; \
+ c0 += lo; hi += (c0<lo); \
+ c1 += hi; c2 += (c1<hi); \
} while(0)
# define mul_add_c2(a,b,c0,c1,c2) do { \
BN_ULONG ta = (a), tb = (b), tt; \
BN_ULONG lo = ta * tb; \
BN_ULONG hi = BN_UMULT_HIGH(ta,tb); \
- c0 += lo; tt = hi + ((c0<lo)?1:0); \
- c1 += tt; c2 += (c1<tt)?1:0; \
- c0 += lo; hi += (c0<lo)?1:0; \
- c1 += hi; c2 += (c1<hi)?1:0; \
+ c0 += lo; tt = hi + (c0<lo); \
+ c1 += tt; c2 += (c1<tt); \
+ c0 += lo; hi += (c0<lo); \
+ c1 += hi; c2 += (c1<hi); \
} while(0)
# define sqr_add_c(a,i,c0,c1,c2) do { \
BN_ULONG ta = (a)[i]; \
BN_ULONG lo = ta * ta; \
BN_ULONG hi = BN_UMULT_HIGH(ta,ta); \
- c0 += lo; hi += (c0<lo)?1:0; \
- c1 += hi; c2 += (c1<hi)?1:0; \
+ c0 += lo; hi += (c0<lo); \
+ c1 += hi; c2 += (c1<hi); \
} while(0)
# define sqr_add_c2(a,i,j,c0,c1,c2) \
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
# else /* !BN_LLONG */
/*
* Keep in mind that additions to hi can not overflow, because
* the high word of a multiplication result cannot be all-ones.
*/
# define mul_add_c(a,b,c0,c1,c2) do { \
BN_ULONG lo = LBITS(a), hi = HBITS(a); \
BN_ULONG bl = LBITS(b), bh = HBITS(b); \
mul64(lo,hi,bl,bh); \
- c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c0 = (c0+lo)&BN_MASK2; hi += (c0<lo); \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
} while(0)
# define mul_add_c2(a,b,c0,c1,c2) do { \
BN_ULONG tt; \
BN_ULONG lo = LBITS(a), hi = HBITS(a); \
BN_ULONG bl = LBITS(b), bh = HBITS(b); \
mul64(lo,hi,bl,bh); \
tt = hi; \
- c0 = (c0+lo)&BN_MASK2; if (c0<lo) tt++; \
- c1 = (c1+tt)&BN_MASK2; if (c1<tt) c2++; \
- c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c0 = (c0+lo)&BN_MASK2; tt += (c0<lo); \
+ c1 = (c1+tt)&BN_MASK2; c2 += (c1<tt); \
+ c0 = (c0+lo)&BN_MASK2; hi += (c0<lo); \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
} while(0)
# define sqr_add_c(a,i,c0,c1,c2) do { \
BN_ULONG lo, hi; \
sqr64(lo,hi,(a)[i]); \
- c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \
- c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ c0 = (c0+lo)&BN_MASK2; hi += (c0<lo); \
+ c1 = (c1+hi)&BN_MASK2; c2 += (c1<hi); \
} while(0)
# define sqr_add_c2(a,i,j,c0,c1,c2) \
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
# endif /* !BN_LLONG */
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
{
BN_ULONG c1, c2, c3;
c1 = 0;
c2 = 0;
c3 = 0;
mul_add_c(a[0], b[0], c1, c2, c3);
r[0] = c1;
c1 = 0;
mul_add_c(a[0], b[1], c2, c3, c1);
mul_add_c(a[1], b[0], c2, c3, c1);
r[1] = c2;
c2 = 0;
mul_add_c(a[2], b[0], c3, c1, c2);
mul_add_c(a[1], b[1], c3, c1, c2);
mul_add_c(a[0], b[2], c3, c1, c2);
r[2] = c3;
c3 = 0;
mul_add_c(a[0], b[3], c1, c2, c3);
mul_add_c(a[1], b[2], c1, c2, c3);
mul_add_c(a[2], b[1], c1, c2, c3);
mul_add_c(a[3], b[0], c1, c2, c3);
r[3] = c1;
c1 = 0;
mul_add_c(a[4], b[0], c2, c3, c1);
mul_add_c(a[3], b[1], c2, c3, c1);
mul_add_c(a[2], b[2], c2, c3, c1);
mul_add_c(a[1], b[3], c2, c3, c1);
mul_add_c(a[0], b[4], c2, c3, c1);
r[4] = c2;
c2 = 0;
mul_add_c(a[0], b[5], c3, c1, c2);
mul_add_c(a[1], b[4], c3, c1, c2);
mul_add_c(a[2], b[3], c3, c1, c2);
mul_add_c(a[3], b[2], c3, c1, c2);
mul_add_c(a[4], b[1], c3, c1, c2);
mul_add_c(a[5], b[0], c3, c1, c2);
r[5] = c3;
c3 = 0;
mul_add_c(a[6], b[0], c1, c2, c3);
mul_add_c(a[5], b[1], c1, c2, c3);
mul_add_c(a[4], b[2], c1, c2, c3);
mul_add_c(a[3], b[3], c1, c2, c3);
mul_add_c(a[2], b[4], c1, c2, c3);
mul_add_c(a[1], b[5], c1, c2, c3);
mul_add_c(a[0], b[6], c1, c2, c3);
r[6] = c1;
c1 = 0;
mul_add_c(a[0], b[7], c2, c3, c1);
mul_add_c(a[1], b[6], c2, c3, c1);
mul_add_c(a[2], b[5], c2, c3, c1);
mul_add_c(a[3], b[4], c2, c3, c1);
mul_add_c(a[4], b[3], c2, c3, c1);
mul_add_c(a[5], b[2], c2, c3, c1);
mul_add_c(a[6], b[1], c2, c3, c1);
mul_add_c(a[7], b[0], c2, c3, c1);
r[7] = c2;
c2 = 0;
mul_add_c(a[7], b[1], c3, c1, c2);
mul_add_c(a[6], b[2], c3, c1, c2);
mul_add_c(a[5], b[3], c3, c1, c2);
mul_add_c(a[4], b[4], c3, c1, c2);
mul_add_c(a[3], b[5], c3, c1, c2);
mul_add_c(a[2], b[6], c3, c1, c2);
mul_add_c(a[1], b[7], c3, c1, c2);
r[8] = c3;
c3 = 0;
mul_add_c(a[2], b[7], c1, c2, c3);
mul_add_c(a[3], b[6], c1, c2, c3);
mul_add_c(a[4], b[5], c1, c2, c3);
mul_add_c(a[5], b[4], c1, c2, c3);
mul_add_c(a[6], b[3], c1, c2, c3);
mul_add_c(a[7], b[2], c1, c2, c3);
r[9] = c1;
c1 = 0;
mul_add_c(a[7], b[3], c2, c3, c1);
mul_add_c(a[6], b[4], c2, c3, c1);
mul_add_c(a[5], b[5], c2, c3, c1);
mul_add_c(a[4], b[6], c2, c3, c1);
mul_add_c(a[3], b[7], c2, c3, c1);
r[10] = c2;
c2 = 0;
mul_add_c(a[4], b[7], c3, c1, c2);
mul_add_c(a[5], b[6], c3, c1, c2);
mul_add_c(a[6], b[5], c3, c1, c2);
mul_add_c(a[7], b[4], c3, c1, c2);
r[11] = c3;
c3 = 0;
mul_add_c(a[7], b[5], c1, c2, c3);
mul_add_c(a[6], b[6], c1, c2, c3);
mul_add_c(a[5], b[7], c1, c2, c3);
r[12] = c1;
c1 = 0;
mul_add_c(a[6], b[7], c2, c3, c1);
mul_add_c(a[7], b[6], c2, c3, c1);
r[13] = c2;
c2 = 0;
mul_add_c(a[7], b[7], c3, c1, c2);
r[14] = c3;
r[15] = c1;
}
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
{
BN_ULONG c1, c2, c3;
c1 = 0;
c2 = 0;
c3 = 0;
mul_add_c(a[0], b[0], c1, c2, c3);
r[0] = c1;
c1 = 0;
mul_add_c(a[0], b[1], c2, c3, c1);
mul_add_c(a[1], b[0], c2, c3, c1);
r[1] = c2;
c2 = 0;
mul_add_c(a[2], b[0], c3, c1, c2);
mul_add_c(a[1], b[1], c3, c1, c2);
mul_add_c(a[0], b[2], c3, c1, c2);
r[2] = c3;
c3 = 0;
mul_add_c(a[0], b[3], c1, c2, c3);
mul_add_c(a[1], b[2], c1, c2, c3);
mul_add_c(a[2], b[1], c1, c2, c3);
mul_add_c(a[3], b[0], c1, c2, c3);
r[3] = c1;
c1 = 0;
mul_add_c(a[3], b[1], c2, c3, c1);
mul_add_c(a[2], b[2], c2, c3, c1);
mul_add_c(a[1], b[3], c2, c3, c1);
r[4] = c2;
c2 = 0;
mul_add_c(a[2], b[3], c3, c1, c2);
mul_add_c(a[3], b[2], c3, c1, c2);
r[5] = c3;
c3 = 0;
mul_add_c(a[3], b[3], c1, c2, c3);
r[6] = c1;
r[7] = c2;
}
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
{
BN_ULONG c1, c2, c3;
c1 = 0;
c2 = 0;
c3 = 0;
sqr_add_c(a, 0, c1, c2, c3);
r[0] = c1;
c1 = 0;
sqr_add_c2(a, 1, 0, c2, c3, c1);
r[1] = c2;
c2 = 0;
sqr_add_c(a, 1, c3, c1, c2);
sqr_add_c2(a, 2, 0, c3, c1, c2);
r[2] = c3;
c3 = 0;
sqr_add_c2(a, 3, 0, c1, c2, c3);
sqr_add_c2(a, 2, 1, c1, c2, c3);
r[3] = c1;
c1 = 0;
sqr_add_c(a, 2, c2, c3, c1);
sqr_add_c2(a, 3, 1, c2, c3, c1);
sqr_add_c2(a, 4, 0, c2, c3, c1);
r[4] = c2;
c2 = 0;
sqr_add_c2(a, 5, 0, c3, c1, c2);
sqr_add_c2(a, 4, 1, c3, c1, c2);
sqr_add_c2(a, 3, 2, c3, c1, c2);
r[5] = c3;
c3 = 0;
sqr_add_c(a, 3, c1, c2, c3);
sqr_add_c2(a, 4, 2, c1, c2, c3);
sqr_add_c2(a, 5, 1, c1, c2, c3);
sqr_add_c2(a, 6, 0, c1, c2, c3);
r[6] = c1;
c1 = 0;
sqr_add_c2(a, 7, 0, c2, c3, c1);
sqr_add_c2(a, 6, 1, c2, c3, c1);
sqr_add_c2(a, 5, 2, c2, c3, c1);
sqr_add_c2(a, 4, 3, c2, c3, c1);
r[7] = c2;
c2 = 0;
sqr_add_c(a, 4, c3, c1, c2);
sqr_add_c2(a, 5, 3, c3, c1, c2);
sqr_add_c2(a, 6, 2, c3, c1, c2);
sqr_add_c2(a, 7, 1, c3, c1, c2);
r[8] = c3;
c3 = 0;
sqr_add_c2(a, 7, 2, c1, c2, c3);
sqr_add_c2(a, 6, 3, c1, c2, c3);
sqr_add_c2(a, 5, 4, c1, c2, c3);
r[9] = c1;
c1 = 0;
sqr_add_c(a, 5, c2, c3, c1);
sqr_add_c2(a, 6, 4, c2, c3, c1);
sqr_add_c2(a, 7, 3, c2, c3, c1);
r[10] = c2;
c2 = 0;
sqr_add_c2(a, 7, 4, c3, c1, c2);
sqr_add_c2(a, 6, 5, c3, c1, c2);
r[11] = c3;
c3 = 0;
sqr_add_c(a, 6, c1, c2, c3);
sqr_add_c2(a, 7, 5, c1, c2, c3);
r[12] = c1;
c1 = 0;
sqr_add_c2(a, 7, 6, c2, c3, c1);
r[13] = c2;
c2 = 0;
sqr_add_c(a, 7, c3, c1, c2);
r[14] = c3;
r[15] = c1;
}
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
{
BN_ULONG c1, c2, c3;
c1 = 0;
c2 = 0;
c3 = 0;
sqr_add_c(a, 0, c1, c2, c3);
r[0] = c1;
c1 = 0;
sqr_add_c2(a, 1, 0, c2, c3, c1);
r[1] = c2;
c2 = 0;
sqr_add_c(a, 1, c3, c1, c2);
sqr_add_c2(a, 2, 0, c3, c1, c2);
r[2] = c3;
c3 = 0;
sqr_add_c2(a, 3, 0, c1, c2, c3);
sqr_add_c2(a, 2, 1, c1, c2, c3);
r[3] = c1;
c1 = 0;
sqr_add_c(a, 2, c2, c3, c1);
sqr_add_c2(a, 3, 1, c2, c3, c1);
r[4] = c2;
c2 = 0;
sqr_add_c2(a, 3, 2, c3, c1, c2);
r[5] = c3;
c3 = 0;
sqr_add_c(a, 3, c1, c2, c3);
r[6] = c1;
r[7] = c2;
}
# ifdef OPENSSL_NO_ASM
# ifdef OPENSSL_BN_ASM_MONT
# include <alloca.h>
/*
* This is essentially reference implementation, which may or may not
* result in performance improvement. E.g. on IA-32 this routine was
* observed to give 40% faster rsa1024 private key operations and 10%
* faster rsa4096 ones, while on AMD64 it improves rsa1024 sign only
* by 10% and *worsens* rsa4096 sign by 15%. Once again, it's a
* reference implementation, one to be used as starting point for
* platform-specific assembler. Mentioned numbers apply to compiler
* generated code compiled with and without -DOPENSSL_BN_ASM_MONT and
* can vary not only from platform to platform, but even for compiler
* versions. Assembler vs. assembler improvement coefficients can
* [and are known to] differ and are to be documented elsewhere.
*/
int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
const BN_ULONG *np, const BN_ULONG *n0p, int num)
{
BN_ULONG c0, c1, ml, *tp, n0;
# ifdef mul64
BN_ULONG mh;
# endif
volatile BN_ULONG *vp;
int i = 0, j;
# if 0 /* template for platform-specific
* implementation */
if (ap == bp)
return bn_sqr_mont(rp, ap, np, n0p, num);
# endif
vp = tp = alloca((num + 2) * sizeof(BN_ULONG));
n0 = *n0p;
c0 = 0;
ml = bp[0];
# ifdef mul64
mh = HBITS(ml);
ml = LBITS(ml);
for (j = 0; j < num; ++j)
mul(tp[j], ap[j], ml, mh, c0);
# else
for (j = 0; j < num; ++j)
mul(tp[j], ap[j], ml, c0);
# endif
tp[num] = c0;
tp[num + 1] = 0;
goto enter;
for (i = 0; i < num; i++) {
c0 = 0;
ml = bp[i];
# ifdef mul64
mh = HBITS(ml);
ml = LBITS(ml);
for (j = 0; j < num; ++j)
mul_add(tp[j], ap[j], ml, mh, c0);
# else
for (j = 0; j < num; ++j)
mul_add(tp[j], ap[j], ml, c0);
# endif
c1 = (tp[num] + c0) & BN_MASK2;
tp[num] = c1;
tp[num + 1] = (c1 < c0 ? 1 : 0);
enter:
c1 = tp[0];
ml = (c1 * n0) & BN_MASK2;
c0 = 0;
# ifdef mul64
mh = HBITS(ml);
ml = LBITS(ml);
mul_add(c1, np[0], ml, mh, c0);
# else
mul_add(c1, ml, np[0], c0);
# endif
for (j = 1; j < num; j++) {
c1 = tp[j];
# ifdef mul64
mul_add(c1, np[j], ml, mh, c0);
# else
mul_add(c1, ml, np[j], c0);
# endif
tp[j - 1] = c1 & BN_MASK2;
}
c1 = (tp[num] + c0) & BN_MASK2;
tp[num - 1] = c1;
tp[num] = tp[num + 1] + (c1 < c0 ? 1 : 0);
}
if (tp[num] != 0 || tp[num - 1] >= np[num - 1]) {
c0 = bn_sub_words(rp, tp, np, num);
if (tp[num] != 0 || c0 == 0) {
for (i = 0; i < num + 2; i++)
vp[i] = 0;
return 1;
}
}
for (i = 0; i < num; i++)
rp[i] = tp[i], vp[i] = 0;
vp[num] = 0;
vp[num + 1] = 0;
return 1;
}
# else
/*
* Return value of 0 indicates that multiplication/convolution was not
* performed to signal the caller to fall down to alternative/original
* code-path.
*/
int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
const BN_ULONG *np, const BN_ULONG *n0, int num)
{
return 0;
}
# endif /* OPENSSL_BN_ASM_MONT */
# endif
#else /* !BN_MUL_COMBA */
/* hmm... is it faster just to do a multiply? */
# undef bn_sqr_comba4
# undef bn_sqr_comba8
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
{
BN_ULONG t[8];
bn_sqr_normal(r, a, 4, t);
}
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
{
BN_ULONG t[16];
bn_sqr_normal(r, a, 8, t);
}
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
{
r[4] = bn_mul_words(&(r[0]), a, 4, b[0]);
r[5] = bn_mul_add_words(&(r[1]), a, 4, b[1]);
r[6] = bn_mul_add_words(&(r[2]), a, 4, b[2]);
r[7] = bn_mul_add_words(&(r[3]), a, 4, b[3]);
}
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
{
r[8] = bn_mul_words(&(r[0]), a, 8, b[0]);
r[9] = bn_mul_add_words(&(r[1]), a, 8, b[1]);
r[10] = bn_mul_add_words(&(r[2]), a, 8, b[2]);
r[11] = bn_mul_add_words(&(r[3]), a, 8, b[3]);
r[12] = bn_mul_add_words(&(r[4]), a, 8, b[4]);
r[13] = bn_mul_add_words(&(r[5]), a, 8, b[5]);
r[14] = bn_mul_add_words(&(r[6]), a, 8, b[6]);
r[15] = bn_mul_add_words(&(r[7]), a, 8, b[7]);
}
# ifdef OPENSSL_NO_ASM
# ifdef OPENSSL_BN_ASM_MONT
# include <alloca.h>
int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
const BN_ULONG *np, const BN_ULONG *n0p, int num)
{
BN_ULONG c0, c1, *tp, n0 = *n0p;
volatile BN_ULONG *vp;
int i = 0, j;
vp = tp = alloca((num + 2) * sizeof(BN_ULONG));
for (i = 0; i <= num; i++)
tp[i] = 0;
for (i = 0; i < num; i++) {
c0 = bn_mul_add_words(tp, ap, num, bp[i]);
c1 = (tp[num] + c0) & BN_MASK2;
tp[num] = c1;
tp[num + 1] = (c1 < c0 ? 1 : 0);
c0 = bn_mul_add_words(tp, np, num, tp[0] * n0);
c1 = (tp[num] + c0) & BN_MASK2;
tp[num] = c1;
tp[num + 1] += (c1 < c0 ? 1 : 0);
for (j = 0; j <= num; j++)
tp[j] = tp[j + 1];
}
if (tp[num] != 0 || tp[num - 1] >= np[num - 1]) {
c0 = bn_sub_words(rp, tp, np, num);
if (tp[num] != 0 || c0 == 0) {
for (i = 0; i < num + 2; i++)
vp[i] = 0;
return 1;
}
}
for (i = 0; i < num; i++)
rp[i] = tp[i], vp[i] = 0;
vp[num] = 0;
vp[num + 1] = 0;
return 1;
}
# else
int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
const BN_ULONG *np, const BN_ULONG *n0, int num)
{
return 0;
}
# endif /* OPENSSL_BN_ASM_MONT */
# endif
#endif /* !BN_MUL_COMBA */
diff --git a/crypto/bn/bn_blind.c b/crypto/bn/bn_blind.c
index 0b6d1bccc2a2..7e5a1c52e27d 100644
--- a/crypto/bn/bn_blind.c
+++ b/crypto/bn/bn_blind.c
@@ -1,298 +1,313 @@
/*
* Copyright 1998-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/opensslconf.h>
#include "internal/cryptlib.h"
#include "bn_local.h"
#define BN_BLINDING_COUNTER 32
+struct bn_blinding_st {
+ BIGNUM *A;
+ BIGNUM *Ai;
+ BIGNUM *e;
+ BIGNUM *mod; /* just a reference */
+ CRYPTO_THREAD_ID tid;
+ int counter;
+ unsigned long flags;
+ BN_MONT_CTX *m_ctx;
+ int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+ CRYPTO_RWLOCK *lock;
+};
+
BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod)
{
BN_BLINDING *ret = NULL;
bn_check_top(mod);
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
BN_BLINDING_set_current_thread(ret);
if (A != NULL) {
if ((ret->A = BN_dup(A)) == NULL)
goto err;
}
if (Ai != NULL) {
if ((ret->Ai = BN_dup(Ai)) == NULL)
goto err;
}
/* save a copy of mod in the BN_BLINDING structure */
if ((ret->mod = BN_dup(mod)) == NULL)
goto err;
if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
/*
* Set the counter to the special value -1 to indicate that this is
* never-used fresh blinding that does not need updating before first
* use.
*/
ret->counter = -1;
return ret;
err:
BN_BLINDING_free(ret);
return NULL;
}
void BN_BLINDING_free(BN_BLINDING *r)
{
if (r == NULL)
return;
BN_free(r->A);
BN_free(r->Ai);
BN_free(r->e);
BN_free(r->mod);
CRYPTO_THREAD_lock_free(r->lock);
OPENSSL_free(r);
}
int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
{
int ret = 0;
if ((b->A == NULL) || (b->Ai == NULL)) {
ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED);
goto err;
}
if (b->counter == -1)
b->counter = 0;
if (++b->counter == BN_BLINDING_COUNTER && b->e != NULL &&
!(b->flags & BN_BLINDING_NO_RECREATE)) {
/* re-create blinding parameters */
if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL))
goto err;
} else if (!(b->flags & BN_BLINDING_NO_UPDATE)) {
if (b->m_ctx != NULL) {
if (!bn_mul_mont_fixed_top(b->Ai, b->Ai, b->Ai, b->m_ctx, ctx)
|| !bn_mul_mont_fixed_top(b->A, b->A, b->A, b->m_ctx, ctx))
goto err;
} else {
if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx)
|| !BN_mod_mul(b->A, b->A, b->A, b->mod, ctx))
goto err;
}
}
ret = 1;
err:
if (b->counter == BN_BLINDING_COUNTER)
b->counter = 0;
return ret;
}
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
{
return BN_BLINDING_convert_ex(n, NULL, b, ctx);
}
int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx)
{
int ret = 1;
bn_check_top(n);
if ((b->A == NULL) || (b->Ai == NULL)) {
ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED);
return 0;
}
if (b->counter == -1)
/* Fresh blinding, doesn't need updating. */
b->counter = 0;
else if (!BN_BLINDING_update(b, ctx))
return 0;
if (r != NULL && (BN_copy(r, b->Ai) == NULL))
return 0;
if (b->m_ctx != NULL)
ret = BN_mod_mul_montgomery(n, n, b->A, b->m_ctx, ctx);
else
ret = BN_mod_mul(n, n, b->A, b->mod, ctx);
return ret;
}
int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
{
return BN_BLINDING_invert_ex(n, NULL, b, ctx);
}
int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
BN_CTX *ctx)
{
int ret;
bn_check_top(n);
if (r == NULL && (r = b->Ai) == NULL) {
ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED);
return 0;
}
if (b->m_ctx != NULL) {
/* ensure that BN_mod_mul_montgomery takes pre-defined path */
if (n->dmax >= r->top) {
size_t i, rtop = r->top, ntop = n->top;
BN_ULONG mask;
for (i = 0; i < rtop; i++) {
mask = (BN_ULONG)0 - ((i - ntop) >> (8 * sizeof(i) - 1));
n->d[i] &= mask;
}
mask = (BN_ULONG)0 - ((rtop - ntop) >> (8 * sizeof(ntop) - 1));
/* always true, if (rtop >= ntop) n->top = r->top; */
n->top = (int)(rtop & ~mask) | (ntop & mask);
n->flags |= (BN_FLG_FIXED_TOP & ~mask);
}
- ret = BN_mod_mul_montgomery(n, n, r, b->m_ctx, ctx);
+ ret = bn_mul_mont_fixed_top(n, n, r, b->m_ctx, ctx);
+ bn_correct_top_consttime(n);
} else {
ret = BN_mod_mul(n, n, r, b->mod, ctx);
}
bn_check_top(n);
return ret;
}
int BN_BLINDING_is_current_thread(BN_BLINDING *b)
{
return CRYPTO_THREAD_compare_id(CRYPTO_THREAD_get_current_id(), b->tid);
}
void BN_BLINDING_set_current_thread(BN_BLINDING *b)
{
b->tid = CRYPTO_THREAD_get_current_id();
}
int BN_BLINDING_lock(BN_BLINDING *b)
{
return CRYPTO_THREAD_write_lock(b->lock);
}
int BN_BLINDING_unlock(BN_BLINDING *b)
{
return CRYPTO_THREAD_unlock(b->lock);
}
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b)
{
return b->flags;
}
void BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags)
{
b->flags = flags;
}
BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
int (*bn_mod_exp) (BIGNUM *r,
const BIGNUM *a,
const BIGNUM *p,
const BIGNUM *m,
BN_CTX *ctx,
BN_MONT_CTX *m_ctx),
BN_MONT_CTX *m_ctx)
{
int retry_counter = 32;
BN_BLINDING *ret = NULL;
if (b == NULL)
ret = BN_BLINDING_new(NULL, NULL, m);
else
ret = b;
if (ret == NULL)
goto err;
if (ret->A == NULL && (ret->A = BN_new()) == NULL)
goto err;
if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL)
goto err;
if (e != NULL) {
BN_free(ret->e);
ret->e = BN_dup(e);
}
if (ret->e == NULL)
goto err;
if (bn_mod_exp != NULL)
ret->bn_mod_exp = bn_mod_exp;
if (m_ctx != NULL)
ret->m_ctx = m_ctx;
do {
int rv;
if (!BN_priv_rand_range_ex(ret->A, ret->mod, 0, ctx))
goto err;
if (int_bn_mod_inverse(ret->Ai, ret->A, ret->mod, ctx, &rv))
break;
/*
* this should almost never happen for good RSA keys
*/
if (!rv)
goto err;
if (retry_counter-- == 0) {
ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS);
goto err;
}
} while (1);
if (ret->bn_mod_exp != NULL && ret->m_ctx != NULL) {
if (!ret->bn_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx, ret->m_ctx))
goto err;
} else {
if (!BN_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx))
goto err;
}
if (ret->m_ctx != NULL) {
if (!bn_to_mont_fixed_top(ret->Ai, ret->Ai, ret->m_ctx, ctx)
|| !bn_to_mont_fixed_top(ret->A, ret->A, ret->m_ctx, ctx))
goto err;
}
return ret;
err:
if (b == NULL) {
BN_BLINDING_free(ret);
ret = NULL;
}
return ret;
}
diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c
index 7ad6842560b4..cf1bfe8ab085 100644
--- a/crypto/bn/bn_lib.c
+++ b/crypto/bn/bn_lib.c
@@ -1,1041 +1,1063 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <assert.h>
#include <limits.h>
#include "internal/cryptlib.h"
#include "internal/endian.h"
#include "bn_local.h"
#include <openssl/opensslconf.h>
#include "internal/constant_time.h"
/* This stuff appears to be completely unused, so is deprecated */
#ifndef OPENSSL_NO_DEPRECATED_0_9_8
/*-
* For a 32 bit machine
* 2 - 4 == 128
* 3 - 8 == 256
* 4 - 16 == 512
* 5 - 32 == 1024
* 6 - 64 == 2048
* 7 - 128 == 4096
* 8 - 256 == 8192
*/
static int bn_limit_bits = 0;
static int bn_limit_num = 8; /* (1<<bn_limit_bits) */
static int bn_limit_bits_low = 0;
static int bn_limit_num_low = 8; /* (1<<bn_limit_bits_low) */
static int bn_limit_bits_high = 0;
static int bn_limit_num_high = 8; /* (1<<bn_limit_bits_high) */
static int bn_limit_bits_mont = 0;
static int bn_limit_num_mont = 8; /* (1<<bn_limit_bits_mont) */
void BN_set_params(int mult, int high, int low, int mont)
{
if (mult >= 0) {
if (mult > (int)(sizeof(int) * 8) - 1)
mult = sizeof(int) * 8 - 1;
bn_limit_bits = mult;
bn_limit_num = 1 << mult;
}
if (high >= 0) {
if (high > (int)(sizeof(int) * 8) - 1)
high = sizeof(int) * 8 - 1;
bn_limit_bits_high = high;
bn_limit_num_high = 1 << high;
}
if (low >= 0) {
if (low > (int)(sizeof(int) * 8) - 1)
low = sizeof(int) * 8 - 1;
bn_limit_bits_low = low;
bn_limit_num_low = 1 << low;
}
if (mont >= 0) {
if (mont > (int)(sizeof(int) * 8) - 1)
mont = sizeof(int) * 8 - 1;
bn_limit_bits_mont = mont;
bn_limit_num_mont = 1 << mont;
}
}
int BN_get_params(int which)
{
if (which == 0)
return bn_limit_bits;
else if (which == 1)
return bn_limit_bits_high;
else if (which == 2)
return bn_limit_bits_low;
else if (which == 3)
return bn_limit_bits_mont;
else
return 0;
}
#endif
const BIGNUM *BN_value_one(void)
{
static const BN_ULONG data_one = 1L;
static const BIGNUM const_one =
{ (BN_ULONG *)&data_one, 1, 1, 0, BN_FLG_STATIC_DATA };
return &const_one;
}
/*
* Old Visual Studio ARM compiler miscompiles BN_num_bits_word()
* https://mta.openssl.org/pipermail/openssl-users/2018-August/008465.html
*/
#if defined(_MSC_VER) && defined(_ARM_) && defined(_WIN32_WCE) \
&& _MSC_VER>=1400 && _MSC_VER<1501
# define MS_BROKEN_BN_num_bits_word
# pragma optimize("", off)
#endif
int BN_num_bits_word(BN_ULONG l)
{
BN_ULONG x, mask;
int bits = (l != 0);
#if BN_BITS2 > 32
x = l >> 32;
mask = (0 - x) & BN_MASK2;
mask = (0 - (mask >> (BN_BITS2 - 1)));
bits += 32 & mask;
l ^= (x ^ l) & mask;
#endif
x = l >> 16;
mask = (0 - x) & BN_MASK2;
mask = (0 - (mask >> (BN_BITS2 - 1)));
bits += 16 & mask;
l ^= (x ^ l) & mask;
x = l >> 8;
mask = (0 - x) & BN_MASK2;
mask = (0 - (mask >> (BN_BITS2 - 1)));
bits += 8 & mask;
l ^= (x ^ l) & mask;
x = l >> 4;
mask = (0 - x) & BN_MASK2;
mask = (0 - (mask >> (BN_BITS2 - 1)));
bits += 4 & mask;
l ^= (x ^ l) & mask;
x = l >> 2;
mask = (0 - x) & BN_MASK2;
mask = (0 - (mask >> (BN_BITS2 - 1)));
bits += 2 & mask;
l ^= (x ^ l) & mask;
x = l >> 1;
mask = (0 - x) & BN_MASK2;
mask = (0 - (mask >> (BN_BITS2 - 1)));
bits += 1 & mask;
return bits;
}
#ifdef MS_BROKEN_BN_num_bits_word
# pragma optimize("", on)
#endif
/*
* This function still leaks `a->dmax`: it's caller's responsibility to
* expand the input `a` in advance to a public length.
*/
static ossl_inline
int bn_num_bits_consttime(const BIGNUM *a)
{
int j, ret;
unsigned int mask, past_i;
int i = a->top - 1;
bn_check_top(a);
for (j = 0, past_i = 0, ret = 0; j < a->dmax; j++) {
mask = constant_time_eq_int(i, j); /* 0xff..ff if i==j, 0x0 otherwise */
ret += BN_BITS2 & (~mask & ~past_i);
ret += BN_num_bits_word(a->d[j]) & mask;
past_i |= mask; /* past_i will become 0xff..ff after i==j */
}
/*
* if BN_is_zero(a) => i is -1 and ret contains garbage, so we mask the
* final result.
*/
mask = ~(constant_time_eq_int(i, ((int)-1)));
return ret & mask;
}
int BN_num_bits(const BIGNUM *a)
{
int i = a->top - 1;
bn_check_top(a);
if (a->flags & BN_FLG_CONSTTIME) {
/*
* We assume that BIGNUMs flagged as CONSTTIME have also been expanded
* so that a->dmax is not leaking secret information.
*
* In other words, it's the caller's responsibility to ensure `a` has
* been preallocated in advance to a public length if we hit this
* branch.
*
*/
return bn_num_bits_consttime(a);
}
if (BN_is_zero(a))
return 0;
return ((i * BN_BITS2) + BN_num_bits_word(a->d[i]));
}
static void bn_free_d(BIGNUM *a, int clear)
{
if (BN_get_flags(a, BN_FLG_SECURE))
OPENSSL_secure_clear_free(a->d, a->dmax * sizeof(a->d[0]));
else if (clear != 0)
OPENSSL_clear_free(a->d, a->dmax * sizeof(a->d[0]));
else
OPENSSL_free(a->d);
}
void BN_clear_free(BIGNUM *a)
{
if (a == NULL)
return;
if (a->d != NULL && !BN_get_flags(a, BN_FLG_STATIC_DATA))
bn_free_d(a, 1);
if (BN_get_flags(a, BN_FLG_MALLOCED)) {
OPENSSL_cleanse(a, sizeof(*a));
OPENSSL_free(a);
}
}
void BN_free(BIGNUM *a)
{
if (a == NULL)
return;
if (!BN_get_flags(a, BN_FLG_STATIC_DATA))
bn_free_d(a, 0);
if (a->flags & BN_FLG_MALLOCED)
OPENSSL_free(a);
}
void bn_init(BIGNUM *a)
{
static BIGNUM nilbn;
*a = nilbn;
bn_check_top(a);
}
BIGNUM *BN_new(void)
{
BIGNUM *ret;
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->flags = BN_FLG_MALLOCED;
bn_check_top(ret);
return ret;
}
BIGNUM *BN_secure_new(void)
{
BIGNUM *ret = BN_new();
if (ret != NULL)
ret->flags |= BN_FLG_SECURE;
return ret;
}
/* This is used by bn_expand2() */
/* The caller MUST check that words > b->dmax before calling this */
static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
{
BN_ULONG *a = NULL;
if (words > (INT_MAX / (4 * BN_BITS2))) {
ERR_raise(ERR_LIB_BN, BN_R_BIGNUM_TOO_LONG);
return NULL;
}
if (BN_get_flags(b, BN_FLG_STATIC_DATA)) {
ERR_raise(ERR_LIB_BN, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
return NULL;
}
if (BN_get_flags(b, BN_FLG_SECURE))
a = OPENSSL_secure_zalloc(words * sizeof(*a));
else
a = OPENSSL_zalloc(words * sizeof(*a));
if (a == NULL) {
ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
assert(b->top <= words);
if (b->top > 0)
memcpy(a, b->d, sizeof(*a) * b->top);
return a;
}
/*
* This is an internal function that should not be used in applications. It
* ensures that 'b' has enough room for a 'words' word number and initialises
* any unused part of b->d with leading zeros. It is mostly used by the
* various BIGNUM routines. If there is an error, NULL is returned. If not,
* 'b' is returned.
*/
BIGNUM *bn_expand2(BIGNUM *b, int words)
{
if (words > b->dmax) {
BN_ULONG *a = bn_expand_internal(b, words);
if (!a)
return NULL;
if (b->d != NULL)
bn_free_d(b, 1);
b->d = a;
b->dmax = words;
}
return b;
}
BIGNUM *BN_dup(const BIGNUM *a)
{
BIGNUM *t;
if (a == NULL)
return NULL;
bn_check_top(a);
t = BN_get_flags(a, BN_FLG_SECURE) ? BN_secure_new() : BN_new();
if (t == NULL)
return NULL;
if (!BN_copy(t, a)) {
BN_free(t);
return NULL;
}
bn_check_top(t);
return t;
}
BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
{
int bn_words;
bn_check_top(b);
bn_words = BN_get_flags(b, BN_FLG_CONSTTIME) ? b->dmax : b->top;
if (a == b)
return a;
if (bn_wexpand(a, bn_words) == NULL)
return NULL;
if (b->top > 0)
memcpy(a->d, b->d, sizeof(b->d[0]) * bn_words);
a->neg = b->neg;
a->top = b->top;
a->flags |= b->flags & BN_FLG_FIXED_TOP;
bn_check_top(a);
return a;
}
#define FLAGS_DATA(flags) ((flags) & (BN_FLG_STATIC_DATA \
| BN_FLG_CONSTTIME \
| BN_FLG_SECURE \
| BN_FLG_FIXED_TOP))
#define FLAGS_STRUCT(flags) ((flags) & (BN_FLG_MALLOCED))
void BN_swap(BIGNUM *a, BIGNUM *b)
{
int flags_old_a, flags_old_b;
BN_ULONG *tmp_d;
int tmp_top, tmp_dmax, tmp_neg;
bn_check_top(a);
bn_check_top(b);
flags_old_a = a->flags;
flags_old_b = b->flags;
tmp_d = a->d;
tmp_top = a->top;
tmp_dmax = a->dmax;
tmp_neg = a->neg;
a->d = b->d;
a->top = b->top;
a->dmax = b->dmax;
a->neg = b->neg;
b->d = tmp_d;
b->top = tmp_top;
b->dmax = tmp_dmax;
b->neg = tmp_neg;
a->flags = FLAGS_STRUCT(flags_old_a) | FLAGS_DATA(flags_old_b);
b->flags = FLAGS_STRUCT(flags_old_b) | FLAGS_DATA(flags_old_a);
bn_check_top(a);
bn_check_top(b);
}
void BN_clear(BIGNUM *a)
{
if (a == NULL)
return;
bn_check_top(a);
if (a->d != NULL)
OPENSSL_cleanse(a->d, sizeof(*a->d) * a->dmax);
a->neg = 0;
a->top = 0;
a->flags &= ~BN_FLG_FIXED_TOP;
}
BN_ULONG BN_get_word(const BIGNUM *a)
{
if (a->top > 1)
return BN_MASK2;
else if (a->top == 1)
return a->d[0];
/* a->top == 0 */
return 0;
}
int BN_set_word(BIGNUM *a, BN_ULONG w)
{
bn_check_top(a);
if (bn_expand(a, (int)sizeof(BN_ULONG) * 8) == NULL)
return 0;
a->neg = 0;
a->d[0] = w;
a->top = (w ? 1 : 0);
a->flags &= ~BN_FLG_FIXED_TOP;
bn_check_top(a);
return 1;
}
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
{
unsigned int i, m;
unsigned int n;
BN_ULONG l;
BIGNUM *bn = NULL;
if (ret == NULL)
ret = bn = BN_new();
if (ret == NULL)
return NULL;
bn_check_top(ret);
/* Skip leading zero's. */
for ( ; len > 0 && *s == 0; s++, len--)
continue;
n = len;
if (n == 0) {
ret->top = 0;
return ret;
}
i = ((n - 1) / BN_BYTES) + 1;
m = ((n - 1) % (BN_BYTES));
if (bn_wexpand(ret, (int)i) == NULL) {
BN_free(bn);
return NULL;
}
ret->top = i;
ret->neg = 0;
l = 0;
while (n--) {
l = (l << 8L) | *(s++);
if (m-- == 0) {
ret->d[--i] = l;
l = 0;
m = BN_BYTES - 1;
}
}
/*
* need to call this due to clear byte at top if avoiding having the top
* bit set (-ve number)
*/
bn_correct_top(ret);
return ret;
}
typedef enum {big, little} endianess_t;
/* ignore negative */
static
int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianess_t endianess)
{
int n;
size_t i, lasti, j, atop, mask;
BN_ULONG l;
/*
* In case |a| is fixed-top, BN_num_bytes can return bogus length,
* but it's assumed that fixed-top inputs ought to be "nominated"
* even for padded output, so it works out...
*/
n = BN_num_bytes(a);
if (tolen == -1) {
tolen = n;
} else if (tolen < n) { /* uncommon/unlike case */
BIGNUM temp = *a;
bn_correct_top(&temp);
n = BN_num_bytes(&temp);
if (tolen < n)
return -1;
}
/* Swipe through whole available data and don't give away padded zero. */
atop = a->dmax * BN_BYTES;
if (atop == 0) {
if (tolen != 0)
memset(to, '\0', tolen);
return tolen;
}
lasti = atop - 1;
atop = a->top * BN_BYTES;
if (endianess == big)
to += tolen; /* start from the end of the buffer */
for (i = 0, j = 0; j < (size_t)tolen; j++) {
unsigned char val;
l = a->d[i / BN_BYTES];
mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1));
val = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask);
if (endianess == big)
*--to = val;
else
*to++ = val;
i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */
}
return tolen;
}
int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
{
if (tolen < 0)
return -1;
return bn2binpad(a, to, tolen, big);
}
int BN_bn2bin(const BIGNUM *a, unsigned char *to)
{
return bn2binpad(a, to, -1, big);
}
BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret)
{
unsigned int i, m;
unsigned int n;
BN_ULONG l;
BIGNUM *bn = NULL;
if (ret == NULL)
ret = bn = BN_new();
if (ret == NULL)
return NULL;
bn_check_top(ret);
s += len;
/* Skip trailing zeroes. */
for ( ; len > 0 && s[-1] == 0; s--, len--)
continue;
n = len;
if (n == 0) {
ret->top = 0;
return ret;
}
i = ((n - 1) / BN_BYTES) + 1;
m = ((n - 1) % (BN_BYTES));
if (bn_wexpand(ret, (int)i) == NULL) {
BN_free(bn);
return NULL;
}
ret->top = i;
ret->neg = 0;
l = 0;
while (n--) {
s--;
l = (l << 8L) | *s;
if (m-- == 0) {
ret->d[--i] = l;
l = 0;
m = BN_BYTES - 1;
}
}
/*
* need to call this due to clear byte at top if avoiding having the top
* bit set (-ve number)
*/
bn_correct_top(ret);
return ret;
}
int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen)
{
if (tolen < 0)
return -1;
return bn2binpad(a, to, tolen, little);
}
BIGNUM *BN_native2bn(const unsigned char *s, int len, BIGNUM *ret)
{
DECLARE_IS_ENDIAN;
if (IS_LITTLE_ENDIAN)
return BN_lebin2bn(s, len, ret);
return BN_bin2bn(s, len, ret);
}
int BN_bn2nativepad(const BIGNUM *a, unsigned char *to, int tolen)
{
DECLARE_IS_ENDIAN;
if (IS_LITTLE_ENDIAN)
return BN_bn2lebinpad(a, to, tolen);
return BN_bn2binpad(a, to, tolen);
}
int BN_ucmp(const BIGNUM *a, const BIGNUM *b)
{
int i;
BN_ULONG t1, t2, *ap, *bp;
bn_check_top(a);
bn_check_top(b);
i = a->top - b->top;
if (i != 0)
return i;
ap = a->d;
bp = b->d;
for (i = a->top - 1; i >= 0; i--) {
t1 = ap[i];
t2 = bp[i];
if (t1 != t2)
return ((t1 > t2) ? 1 : -1);
}
return 0;
}
int BN_cmp(const BIGNUM *a, const BIGNUM *b)
{
int i;
int gt, lt;
BN_ULONG t1, t2;
if ((a == NULL) || (b == NULL)) {
if (a != NULL)
return -1;
else if (b != NULL)
return 1;
else
return 0;
}
bn_check_top(a);
bn_check_top(b);
if (a->neg != b->neg) {
if (a->neg)
return -1;
else
return 1;
}
if (a->neg == 0) {
gt = 1;
lt = -1;
} else {
gt = -1;
lt = 1;
}
if (a->top > b->top)
return gt;
if (a->top < b->top)
return lt;
for (i = a->top - 1; i >= 0; i--) {
t1 = a->d[i];
t2 = b->d[i];
if (t1 > t2)
return gt;
if (t1 < t2)
return lt;
}
return 0;
}
int BN_set_bit(BIGNUM *a, int n)
{
int i, j, k;
if (n < 0)
return 0;
i = n / BN_BITS2;
j = n % BN_BITS2;
if (a->top <= i) {
if (bn_wexpand(a, i + 1) == NULL)
return 0;
for (k = a->top; k < i + 1; k++)
a->d[k] = 0;
a->top = i + 1;
a->flags &= ~BN_FLG_FIXED_TOP;
}
a->d[i] |= (((BN_ULONG)1) << j);
bn_check_top(a);
return 1;
}
int BN_clear_bit(BIGNUM *a, int n)
{
int i, j;
bn_check_top(a);
if (n < 0)
return 0;
i = n / BN_BITS2;
j = n % BN_BITS2;
if (a->top <= i)
return 0;
a->d[i] &= (~(((BN_ULONG)1) << j));
bn_correct_top(a);
return 1;
}
int BN_is_bit_set(const BIGNUM *a, int n)
{
int i, j;
bn_check_top(a);
if (n < 0)
return 0;
i = n / BN_BITS2;
j = n % BN_BITS2;
if (a->top <= i)
return 0;
return (int)(((a->d[i]) >> j) & ((BN_ULONG)1));
}
int BN_mask_bits(BIGNUM *a, int n)
{
int b, w;
bn_check_top(a);
if (n < 0)
return 0;
w = n / BN_BITS2;
b = n % BN_BITS2;
if (w >= a->top)
return 0;
if (b == 0)
a->top = w;
else {
a->top = w + 1;
a->d[w] &= ~(BN_MASK2 << b);
}
bn_correct_top(a);
return 1;
}
void BN_set_negative(BIGNUM *a, int b)
{
if (b && !BN_is_zero(a))
a->neg = 1;
else
a->neg = 0;
}
int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
{
int i;
BN_ULONG aa, bb;
if (n == 0)
return 0;
aa = a[n - 1];
bb = b[n - 1];
if (aa != bb)
return ((aa > bb) ? 1 : -1);
for (i = n - 2; i >= 0; i--) {
aa = a[i];
bb = b[i];
if (aa != bb)
return ((aa > bb) ? 1 : -1);
}
return 0;
}
/*
* Here follows a specialised variants of bn_cmp_words(). It has the
* capability of performing the operation on arrays of different sizes. The
* sizes of those arrays is expressed through cl, which is the common length
* ( basically, min(len(a),len(b)) ), and dl, which is the delta between the
* two lengths, calculated as len(a)-len(b). All lengths are the number of
* BN_ULONGs...
*/
int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl)
{
int n, i;
n = cl - 1;
if (dl < 0) {
for (i = dl; i < 0; i++) {
if (b[n - i] != 0)
return -1; /* a < b */
}
}
if (dl > 0) {
for (i = dl; i > 0; i--) {
if (a[n + i] != 0)
return 1; /* a > b */
}
}
return bn_cmp_words(a, b, cl);
}
/*-
* Constant-time conditional swap of a and b.
* a and b are swapped if condition is not 0.
* nwords is the number of words to swap.
* Assumes that at least nwords are allocated in both a and b.
* Assumes that no more than nwords are used by either a or b.
*/
void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords)
{
BN_ULONG t;
int i;
if (a == b)
return;
bn_wcheck_size(a, nwords);
bn_wcheck_size(b, nwords);
condition = ((~condition & ((condition - 1))) >> (BN_BITS2 - 1)) - 1;
t = (a->top ^ b->top) & condition;
a->top ^= t;
b->top ^= t;
t = (a->neg ^ b->neg) & condition;
a->neg ^= t;
b->neg ^= t;
/*-
* BN_FLG_STATIC_DATA: indicates that data may not be written to. Intention
* is actually to treat it as it's read-only data, and some (if not most)
* of it does reside in read-only segment. In other words observation of
* BN_FLG_STATIC_DATA in BN_consttime_swap should be treated as fatal
* condition. It would either cause SEGV or effectively cause data
* corruption.
*
* BN_FLG_MALLOCED: refers to BN structure itself, and hence must be
* preserved.
*
* BN_FLG_SECURE: must be preserved, because it determines how x->d was
* allocated and hence how to free it.
*
* BN_FLG_CONSTTIME: sufficient to mask and swap
*
* BN_FLG_FIXED_TOP: indicates that we haven't called bn_correct_top() on
* the data, so the d array may be padded with additional 0 values (i.e.
* top could be greater than the minimal value that it could be). We should
* be swapping it
*/
#define BN_CONSTTIME_SWAP_FLAGS (BN_FLG_CONSTTIME | BN_FLG_FIXED_TOP)
t = ((a->flags ^ b->flags) & BN_CONSTTIME_SWAP_FLAGS) & condition;
a->flags ^= t;
b->flags ^= t;
/* conditionally swap the data */
for (i = 0; i < nwords; i++) {
t = (a->d[i] ^ b->d[i]) & condition;
a->d[i] ^= t;
b->d[i] ^= t;
}
}
#undef BN_CONSTTIME_SWAP_FLAGS
/* Bits of security, see SP800-57 */
int BN_security_bits(int L, int N)
{
int secbits, bits;
if (L >= 15360)
secbits = 256;
else if (L >= 7680)
secbits = 192;
else if (L >= 3072)
secbits = 128;
else if (L >= 2048)
secbits = 112;
else if (L >= 1024)
secbits = 80;
else
return 0;
if (N == -1)
return secbits;
bits = N / 2;
if (bits < 80)
return 0;
return bits >= secbits ? secbits : bits;
}
void BN_zero_ex(BIGNUM *a)
{
a->neg = 0;
a->top = 0;
a->flags &= ~BN_FLG_FIXED_TOP;
}
int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w)
{
return ((a->top == 1) && (a->d[0] == w)) || ((w == 0) && (a->top == 0));
}
int BN_is_zero(const BIGNUM *a)
{
return a->top == 0;
}
int BN_is_one(const BIGNUM *a)
{
return BN_abs_is_word(a, 1) && !a->neg;
}
int BN_is_word(const BIGNUM *a, const BN_ULONG w)
{
return BN_abs_is_word(a, w) && (!w || !a->neg);
}
int BN_is_odd(const BIGNUM *a)
{
return (a->top > 0) && (a->d[0] & 1);
}
int BN_is_negative(const BIGNUM *a)
{
return (a->neg != 0);
}
int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
BN_CTX *ctx)
{
return BN_mod_mul_montgomery(r, a, &(mont->RR), mont, ctx);
}
void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags)
{
dest->d = b->d;
dest->top = b->top;
dest->dmax = b->dmax;
dest->neg = b->neg;
dest->flags = ((dest->flags & BN_FLG_MALLOCED)
| (b->flags & ~BN_FLG_MALLOCED)
| BN_FLG_STATIC_DATA | flags);
}
BN_GENCB *BN_GENCB_new(void)
{
BN_GENCB *ret;
if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) {
ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
return ret;
}
void BN_GENCB_free(BN_GENCB *cb)
{
if (cb == NULL)
return;
OPENSSL_free(cb);
}
void BN_set_flags(BIGNUM *b, int n)
{
b->flags |= n;
}
int BN_get_flags(const BIGNUM *b, int n)
{
return b->flags & n;
}
/* Populate a BN_GENCB structure with an "old"-style callback */
void BN_GENCB_set_old(BN_GENCB *gencb, void (*callback) (int, int, void *),
void *cb_arg)
{
BN_GENCB *tmp_gencb = gencb;
tmp_gencb->ver = 1;
tmp_gencb->arg = cb_arg;
tmp_gencb->cb.cb_1 = callback;
}
/* Populate a BN_GENCB structure with a "new"-style callback */
void BN_GENCB_set(BN_GENCB *gencb, int (*callback) (int, int, BN_GENCB *),
void *cb_arg)
{
BN_GENCB *tmp_gencb = gencb;
tmp_gencb->ver = 2;
tmp_gencb->arg = cb_arg;
tmp_gencb->cb.cb_2 = callback;
}
void *BN_GENCB_get_arg(BN_GENCB *cb)
{
return cb->arg;
}
BIGNUM *bn_wexpand(BIGNUM *a, int words)
{
return (words <= a->dmax) ? a : bn_expand2(a, words);
}
+void bn_correct_top_consttime(BIGNUM *a)
+{
+ int j, atop;
+ BN_ULONG limb;
+ unsigned int mask;
+
+ for (j = 0, atop = 0; j < a->dmax; j++) {
+ limb = a->d[j];
+ limb |= 0 - limb;
+ limb >>= BN_BITS2 - 1;
+ limb = 0 - limb;
+ mask = (unsigned int)limb;
+ mask &= constant_time_msb(j - a->top);
+ atop = constant_time_select_int(mask, j + 1, atop);
+ }
+
+ mask = constant_time_eq_int(atop, 0);
+ a->top = atop;
+ a->neg = constant_time_select_int(mask, 0, a->neg);
+ a->flags &= ~BN_FLG_FIXED_TOP;
+}
+
void bn_correct_top(BIGNUM *a)
{
BN_ULONG *ftl;
int tmp_top = a->top;
if (tmp_top > 0) {
for (ftl = &(a->d[tmp_top]); tmp_top > 0; tmp_top--) {
ftl--;
if (*ftl != 0)
break;
}
a->top = tmp_top;
}
if (a->top == 0)
a->neg = 0;
a->flags &= ~BN_FLG_FIXED_TOP;
bn_pollute(a);
}
diff --git a/crypto/bn/bn_local.h b/crypto/bn/bn_local.h
index 2cc445607e18..50e9d26e215b 100644
--- a/crypto/bn/bn_local.h
+++ b/crypto/bn/bn_local.h
@@ -1,712 +1,680 @@
/*
* 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
*/
#ifndef OSSL_CRYPTO_BN_LOCAL_H
# define OSSL_CRYPTO_BN_LOCAL_H
/*
* The EDK2 build doesn't use bn_conf.h; it sets THIRTY_TWO_BIT or
* SIXTY_FOUR_BIT in its own environment since it doesn't re-run our
* Configure script and needs to support both 32-bit and 64-bit.
*/
# include <openssl/opensslconf.h>
# if !defined(OPENSSL_SYS_UEFI)
# include "crypto/bn_conf.h"
# endif
# include "crypto/bn.h"
# include "internal/cryptlib.h"
# include "internal/numbers.h"
/*
* These preprocessor symbols control various aspects of the bignum headers
* and library code. They're not defined by any "normal" configuration, as
* they are intended for development and testing purposes. NB: defining
* them can be useful for debugging application code as well as openssl
* itself. BN_DEBUG - turn on various debugging alterations to the bignum
* code BN_RAND_DEBUG - uses random poisoning of unused words to trip up
* mismanagement of bignum internals. Enable BN_RAND_DEBUG is known to
* break some of the OpenSSL tests.
*/
# if defined(BN_RAND_DEBUG) && !defined(BN_DEBUG)
# define BN_DEBUG
# endif
# if defined(BN_RAND_DEBUG)
# include <openssl/rand.h>
# endif
/*
* This should limit the stack usage due to alloca to about 4K.
* BN_SOFT_LIMIT is a soft limit equivalent to 2*OPENSSL_RSA_MAX_MODULUS_BITS.
* Beyond that size bn_mul_mont is no longer used, and the constant time
* assembler code is disabled, due to the blatant alloca and bn_mul_mont usage.
* Note that bn_mul_mont does an alloca that is hidden away in assembly.
* It is not recommended to do computations with numbers exceeding this limit,
* since the result will be highly version dependent:
* While the current OpenSSL version will use non-optimized, but safe code,
* previous versions will use optimized code, that may crash due to unexpected
* stack overflow, and future versions may very well turn this into a hard
* limit.
* Note however, that it is possible to override the size limit using
* "./config -DBN_SOFT_LIMIT=<limit>" if necessary, and the O/S specific
* stack limit is known and taken into consideration.
*/
# ifndef BN_SOFT_LIMIT
# define BN_SOFT_LIMIT (4096 / BN_BYTES)
# endif
# ifndef OPENSSL_SMALL_FOOTPRINT
# define BN_MUL_COMBA
# define BN_SQR_COMBA
# define BN_RECURSION
# endif
/*
* This next option uses the C libraries (2 word)/(1 word) function. If it is
* not defined, I use my C version (which is slower). The reason for this
* flag is that when the particular C compiler library routine is used, and
* the library is linked with a different compiler, the library is missing.
* This mostly happens when the library is built with gcc and then linked
* using normal cc. This would be a common occurrence because gcc normally
* produces code that is 2 times faster than system compilers for the big
* number stuff. For machines with only one compiler (or shared libraries),
* this should be on. Again this in only really a problem on machines using
* "long long's", are 32bit, and are not using my assembler code.
*/
# if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || \
defined(OPENSSL_SYS_WIN32) || defined(linux)
# define BN_DIV2W
# endif
/*
* 64-bit processor with LP64 ABI
*/
# ifdef SIXTY_FOUR_BIT_LONG
# define BN_ULLONG unsigned long long
# define BN_BITS4 32
# define BN_MASK2 (0xffffffffffffffffL)
# define BN_MASK2l (0xffffffffL)
# define BN_MASK2h (0xffffffff00000000L)
# define BN_MASK2h1 (0xffffffff80000000L)
# define BN_DEC_CONV (10000000000000000000UL)
# define BN_DEC_NUM 19
# define BN_DEC_FMT1 "%lu"
# define BN_DEC_FMT2 "%019lu"
# endif
/*
* 64-bit processor other than LP64 ABI
*/
# ifdef SIXTY_FOUR_BIT
# undef BN_LLONG
# undef BN_ULLONG
# define BN_BITS4 32
# define BN_MASK2 (0xffffffffffffffffLL)
# define BN_MASK2l (0xffffffffL)
# define BN_MASK2h (0xffffffff00000000LL)
# define BN_MASK2h1 (0xffffffff80000000LL)
# define BN_DEC_CONV (10000000000000000000ULL)
# define BN_DEC_NUM 19
# define BN_DEC_FMT1 "%llu"
# define BN_DEC_FMT2 "%019llu"
# endif
# ifdef THIRTY_TWO_BIT
# ifdef BN_LLONG
# if defined(_WIN32) && !defined(__GNUC__)
# define BN_ULLONG unsigned __int64
# else
# define BN_ULLONG unsigned long long
# endif
# endif
# define BN_BITS4 16
# define BN_MASK2 (0xffffffffL)
# define BN_MASK2l (0xffff)
# define BN_MASK2h1 (0xffff8000L)
# define BN_MASK2h (0xffff0000L)
# define BN_DEC_CONV (1000000000L)
# define BN_DEC_NUM 9
# define BN_DEC_FMT1 "%u"
# define BN_DEC_FMT2 "%09u"
# endif
/*-
* Bignum consistency macros
* There is one "API" macro, bn_fix_top(), for stripping leading zeroes from
* bignum data after direct manipulations on the data. There is also an
* "internal" macro, bn_check_top(), for verifying that there are no leading
* zeroes. Unfortunately, some auditing is required due to the fact that
* bn_fix_top() has become an overabused duct-tape because bignum data is
* occasionally passed around in an inconsistent state. So the following
* changes have been made to sort this out;
* - bn_fix_top()s implementation has been moved to bn_correct_top()
* - if BN_DEBUG isn't defined, bn_fix_top() maps to bn_correct_top(), and
* bn_check_top() is as before.
* - if BN_DEBUG *is* defined;
* - bn_check_top() tries to pollute unused words even if the bignum 'top' is
* consistent. (ed: only if BN_RAND_DEBUG is defined)
* - bn_fix_top() maps to bn_check_top() rather than "fixing" anything.
* The idea is to have debug builds flag up inconsistent bignums when they
* occur. If that occurs in a bn_fix_top(), we examine the code in question; if
* the use of bn_fix_top() was appropriate (ie. it follows directly after code
* that manipulates the bignum) it is converted to bn_correct_top(), and if it
* was not appropriate, we convert it permanently to bn_check_top() and track
* down the cause of the bug. Eventually, no internal code should be using the
* bn_fix_top() macro. External applications and libraries should try this with
* their own code too, both in terms of building against the openssl headers
* with BN_DEBUG defined *and* linking with a version of OpenSSL built with it
* defined. This not only improves external code, it provides more test
* coverage for openssl's own code.
*/
# ifdef BN_DEBUG
/*
* The new BN_FLG_FIXED_TOP flag marks vectors that were not treated with
* bn_correct_top, in other words such vectors are permitted to have zeros
* in most significant limbs. Such vectors are used internally to achieve
* execution time invariance for critical operations with private keys.
* It's BN_DEBUG-only flag, because user application is not supposed to
* observe it anyway. Moreover, optimizing compiler would actually remove
* all operations manipulating the bit in question in non-BN_DEBUG build.
*/
# define BN_FLG_FIXED_TOP 0x10000
# ifdef BN_RAND_DEBUG
# define bn_pollute(a) \
do { \
const BIGNUM *_bnum1 = (a); \
if (_bnum1->top < _bnum1->dmax) { \
unsigned char _tmp_char; \
/* We cast away const without the compiler knowing, any \
* *genuinely* constant variables that aren't mutable \
* wouldn't be constructed with top!=dmax. */ \
BN_ULONG *_not_const; \
memcpy(&_not_const, &_bnum1->d, sizeof(_not_const)); \
(void)RAND_bytes(&_tmp_char, 1); /* Debug only - safe to ignore error return */\
memset(_not_const + _bnum1->top, _tmp_char, \
sizeof(*_not_const) * (_bnum1->dmax - _bnum1->top)); \
} \
} while(0)
# else
# define bn_pollute(a)
# endif
# define bn_check_top(a) \
do { \
const BIGNUM *_bnum2 = (a); \
if (_bnum2 != NULL) { \
int _top = _bnum2->top; \
(void)ossl_assert((_top == 0 && !_bnum2->neg) || \
(_top && ((_bnum2->flags & BN_FLG_FIXED_TOP) \
|| _bnum2->d[_top - 1] != 0))); \
bn_pollute(_bnum2); \
} \
} while(0)
# define bn_fix_top(a) bn_check_top(a)
# define bn_check_size(bn, bits) bn_wcheck_size(bn, ((bits+BN_BITS2-1))/BN_BITS2)
# define bn_wcheck_size(bn, words) \
do { \
const BIGNUM *_bnum2 = (bn); \
assert((words) <= (_bnum2)->dmax && \
(words) >= (_bnum2)->top); \
/* avoid unused variable warning with NDEBUG */ \
(void)(_bnum2); \
} while(0)
# else /* !BN_DEBUG */
# define BN_FLG_FIXED_TOP 0
# define bn_pollute(a)
# define bn_check_top(a)
# define bn_fix_top(a) bn_correct_top(a)
# define bn_check_size(bn, bits)
# define bn_wcheck_size(bn, words)
# endif
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
BN_ULONG w);
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
int num);
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
int num);
struct bignum_st {
BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit
* chunks. */
int top; /* Index of last used d +1. */
/* The next are internal book keeping for bn_expand. */
int dmax; /* Size of the d array. */
int neg; /* one if the number is negative */
int flags;
};
/* Used for montgomery multiplication */
struct bn_mont_ctx_st {
int ri; /* number of bits in R */
BIGNUM RR; /* used to convert to montgomery form,
possibly zero-padded */
BIGNUM N; /* The modulus */
BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1 (Ni is only
* stored for bignum algorithm) */
BN_ULONG n0[2]; /* least significant word(s) of Ni; (type
* changed with 0.9.9, was "BN_ULONG n0;"
* before) */
int flags;
};
/*
* Used for reciprocal division/mod functions It cannot be shared between
* threads
*/
struct bn_recp_ctx_st {
BIGNUM N; /* the divisor */
BIGNUM Nr; /* the reciprocal */
int num_bits;
int shift;
int flags;
};
/* Used for slow "generation" functions. */
struct bn_gencb_st {
unsigned int ver; /* To handle binary (in)compatibility */
void *arg; /* callback-specific data */
union {
/* if (ver==1) - handles old style callbacks */
void (*cb_1) (int, int, void *);
/* if (ver==2) - new callback style */
int (*cb_2) (int, int, BN_GENCB *);
} cb;
};
-struct bn_blinding_st {
- BIGNUM *A;
- BIGNUM *Ai;
- BIGNUM *e;
- BIGNUM *mod; /* just a reference */
- CRYPTO_THREAD_ID tid;
- int counter;
- unsigned long flags;
- BN_MONT_CTX *m_ctx;
- int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
- CRYPTO_RWLOCK *lock;
-};
-
/*-
* BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions
*
*
* For window size 'w' (w >= 2) and a random 'b' bits exponent,
* the number of multiplications is a constant plus on average
*
* 2^(w-1) + (b-w)/(w+1);
*
* here 2^(w-1) is for precomputing the table (we actually need
* entries only for windows that have the lowest bit set), and
* (b-w)/(w+1) is an approximation for the expected number of
* w-bit windows, not counting the first one.
*
* Thus we should use
*
* w >= 6 if b > 671
* w = 5 if 671 > b > 239
* w = 4 if 239 > b > 79
* w = 3 if 79 > b > 23
* w <= 2 if 23 > b
*
* (with draws in between). Very small exponents are often selected
* with low Hamming weight, so we use w = 1 for b <= 23.
*/
# define BN_window_bits_for_exponent_size(b) \
((b) > 671 ? 6 : \
(b) > 239 ? 5 : \
(b) > 79 ? 4 : \
(b) > 23 ? 3 : 1)
/*
* BN_mod_exp_mont_consttime is based on the assumption that the L1 data cache
* line width of the target processor is at least the following value.
*/
# define MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH ( 64 )
# define MOD_EXP_CTIME_MIN_CACHE_LINE_MASK (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - 1)
/*
* Window sizes optimized for fixed window size modular exponentiation
* algorithm (BN_mod_exp_mont_consttime). To achieve the security goals of
* BN_mode_exp_mont_consttime, the maximum size of the window must not exceed
* log_2(MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH). Window size thresholds are
* defined for cache line sizes of 32 and 64, cache line sizes where
* log_2(32)=5 and log_2(64)=6 respectively. A window size of 7 should only be
* used on processors that have a 128 byte or greater cache line size.
*/
# if MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 64
# define BN_window_bits_for_ctime_exponent_size(b) \
((b) > 937 ? 6 : \
(b) > 306 ? 5 : \
(b) > 89 ? 4 : \
(b) > 22 ? 3 : 1)
# define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE (6)
# elif MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 32
# define BN_window_bits_for_ctime_exponent_size(b) \
((b) > 306 ? 5 : \
(b) > 89 ? 4 : \
(b) > 22 ? 3 : 1)
# define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE (5)
# endif
/* Pentium pro 16,16,16,32,64 */
/* Alpha 16,16,16,16.64 */
# define BN_MULL_SIZE_NORMAL (16)/* 32 */
# define BN_MUL_RECURSIVE_SIZE_NORMAL (16)/* 32 less than */
# define BN_SQR_RECURSIVE_SIZE_NORMAL (16)/* 32 */
# define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32)/* 32 */
# define BN_MONT_CTX_SET_SIZE_WORD (64)/* 32 */
-/*
- * 2011-02-22 SMS. In various places, a size_t variable or a type cast to
- * size_t was used to perform integer-only operations on pointers. This
- * failed on VMS with 64-bit pointers (CC /POINTER_SIZE = 64) because size_t
- * is still only 32 bits. What's needed in these cases is an integer type
- * with the same size as a pointer, which size_t is not certain to be. The
- * only fix here is VMS-specific.
- */
-# if defined(OPENSSL_SYS_VMS)
-# if __INITIAL_POINTER_SIZE == 64
-# define PTR_SIZE_INT long long
-# else /* __INITIAL_POINTER_SIZE == 64 */
-# define PTR_SIZE_INT int
-# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
-# elif !defined(PTR_SIZE_INT) /* defined(OPENSSL_SYS_VMS) */
-# define PTR_SIZE_INT size_t
-# endif /* defined(OPENSSL_SYS_VMS) [else] */
-
# if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC)
/*
* BN_UMULT_HIGH section.
* If the compiler doesn't support 2*N integer type, then you have to
* replace every N*N multiplication with 4 (N/2)*(N/2) accompanied by some
* shifts and additions which unavoidably results in severe performance
* penalties. Of course provided that the hardware is capable of producing
* 2*N result... That's when you normally start considering assembler
* implementation. However! It should be pointed out that some CPUs (e.g.,
* PowerPC, Alpha, and IA-64) provide *separate* instruction calculating
* the upper half of the product placing the result into a general
* purpose register. Now *if* the compiler supports inline assembler,
* then it's not impossible to implement the "bignum" routines (and have
* the compiler optimize 'em) exhibiting "native" performance in C. That's
* what BN_UMULT_HIGH macro is about:-) Note that more recent compilers do
* support 2*64 integer type, which is also used here.
*/
# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16 && \
(defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG))
# define BN_UMULT_HIGH(a,b) (((uint128_t)(a)*(b))>>64)
# define BN_UMULT_LOHI(low,high,a,b) ({ \
uint128_t ret=(uint128_t)(a)*(b); \
(high)=ret>>64; (low)=ret; })
# elif defined(__alpha) && (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT))
# if defined(__DECC)
# include <c_asm.h>
# define BN_UMULT_HIGH(a,b) (BN_ULONG)asm("umulh %a0,%a1,%v0",(a),(b))
# elif defined(__GNUC__) && __GNUC__>=2
# define BN_UMULT_HIGH(a,b) ({ \
register BN_ULONG ret; \
asm ("umulh %1,%2,%0" \
: "=r"(ret) \
: "r"(a), "r"(b)); \
ret; })
# endif /* compiler */
# elif defined(_ARCH_PPC64) && defined(SIXTY_FOUR_BIT_LONG)
# if defined(__GNUC__) && __GNUC__>=2
# define BN_UMULT_HIGH(a,b) ({ \
register BN_ULONG ret; \
asm ("mulhdu %0,%1,%2" \
: "=r"(ret) \
: "r"(a), "r"(b)); \
ret; })
# endif /* compiler */
# elif (defined(__x86_64) || defined(__x86_64__)) && \
(defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT))
# if defined(__GNUC__) && __GNUC__>=2
# define BN_UMULT_HIGH(a,b) ({ \
register BN_ULONG ret,discard; \
asm ("mulq %3" \
: "=a"(discard),"=d"(ret) \
: "a"(a), "g"(b) \
: "cc"); \
ret; })
# define BN_UMULT_LOHI(low,high,a,b) \
asm ("mulq %3" \
: "=a"(low),"=d"(high) \
: "a"(a),"g"(b) \
: "cc");
# endif
# elif (defined(_M_AMD64) || defined(_M_X64)) && defined(SIXTY_FOUR_BIT)
# if defined(_MSC_VER) && _MSC_VER>=1400
unsigned __int64 __umulh(unsigned __int64 a, unsigned __int64 b);
unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b,
unsigned __int64 *h);
# pragma intrinsic(__umulh,_umul128)
# define BN_UMULT_HIGH(a,b) __umulh((a),(b))
# define BN_UMULT_LOHI(low,high,a,b) ((low)=_umul128((a),(b),&(high)))
# endif
# elif defined(__mips) && (defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG))
# if defined(__GNUC__) && __GNUC__>=2
# define BN_UMULT_HIGH(a,b) ({ \
register BN_ULONG ret; \
asm ("dmultu %1,%2" \
: "=h"(ret) \
: "r"(a), "r"(b) : "l"); \
ret; })
# define BN_UMULT_LOHI(low,high,a,b) \
asm ("dmultu %2,%3" \
: "=l"(low),"=h"(high) \
: "r"(a), "r"(b));
# endif
# elif defined(__aarch64__) && defined(SIXTY_FOUR_BIT_LONG)
# if defined(__GNUC__) && __GNUC__>=2
# define BN_UMULT_HIGH(a,b) ({ \
register BN_ULONG ret; \
asm ("umulh %0,%1,%2" \
: "=r"(ret) \
: "r"(a), "r"(b)); \
ret; })
# endif
# endif /* cpu */
# endif /* OPENSSL_NO_ASM */
# ifdef BN_RAND_DEBUG
# define bn_clear_top2max(a) \
{ \
int ind = (a)->dmax - (a)->top; \
BN_ULONG *ftl = &(a)->d[(a)->top-1]; \
for (; ind != 0; ind--) \
*(++ftl) = 0x0; \
}
# else
# define bn_clear_top2max(a)
# endif
# ifdef BN_LLONG
/*******************************************************************
* Using the long long type, has to be twice as wide as BN_ULONG...
*/
# define Lw(t) (((BN_ULONG)(t))&BN_MASK2)
# define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
# define mul_add(r,a,w,c) { \
BN_ULLONG t; \
t=(BN_ULLONG)w * (a) + (r) + (c); \
(r)= Lw(t); \
(c)= Hw(t); \
}
# define mul(r,a,w,c) { \
BN_ULLONG t; \
t=(BN_ULLONG)w * (a) + (c); \
(r)= Lw(t); \
(c)= Hw(t); \
}
# define sqr(r0,r1,a) { \
BN_ULLONG t; \
t=(BN_ULLONG)(a)*(a); \
(r0)=Lw(t); \
(r1)=Hw(t); \
}
# elif defined(BN_UMULT_LOHI)
# define mul_add(r,a,w,c) { \
BN_ULONG high,low,ret,tmp=(a); \
ret = (r); \
BN_UMULT_LOHI(low,high,w,tmp); \
ret += (c); \
- (c) = (ret<(c))?1:0; \
+ (c) = (ret<(c)); \
(c) += high; \
ret += low; \
- (c) += (ret<low)?1:0; \
+ (c) += (ret<low); \
(r) = ret; \
}
# define mul(r,a,w,c) { \
BN_ULONG high,low,ret,ta=(a); \
BN_UMULT_LOHI(low,high,w,ta); \
ret = low + (c); \
(c) = high; \
- (c) += (ret<low)?1:0; \
+ (c) += (ret<low); \
(r) = ret; \
}
# define sqr(r0,r1,a) { \
BN_ULONG tmp=(a); \
BN_UMULT_LOHI(r0,r1,tmp,tmp); \
}
# elif defined(BN_UMULT_HIGH)
# define mul_add(r,a,w,c) { \
BN_ULONG high,low,ret,tmp=(a); \
ret = (r); \
high= BN_UMULT_HIGH(w,tmp); \
ret += (c); \
low = (w) * tmp; \
- (c) = (ret<(c))?1:0; \
+ (c) = (ret<(c)); \
(c) += high; \
ret += low; \
- (c) += (ret<low)?1:0; \
+ (c) += (ret<low); \
(r) = ret; \
}
# define mul(r,a,w,c) { \
BN_ULONG high,low,ret,ta=(a); \
low = (w) * ta; \
high= BN_UMULT_HIGH(w,ta); \
ret = low + (c); \
(c) = high; \
- (c) += (ret<low)?1:0; \
+ (c) += (ret<low); \
(r) = ret; \
}
# define sqr(r0,r1,a) { \
BN_ULONG tmp=(a); \
(r0) = tmp * tmp; \
(r1) = BN_UMULT_HIGH(tmp,tmp); \
}
# else
/*************************************************************
* No long long type
*/
# define LBITS(a) ((a)&BN_MASK2l)
# define HBITS(a) (((a)>>BN_BITS4)&BN_MASK2l)
# define L2HBITS(a) (((a)<<BN_BITS4)&BN_MASK2)
# define LLBITS(a) ((a)&BN_MASKl)
# define LHBITS(a) (((a)>>BN_BITS2)&BN_MASKl)
# define LL2HBITS(a) ((BN_ULLONG)((a)&BN_MASKl)<<BN_BITS2)
# define mul64(l,h,bl,bh) \
{ \
BN_ULONG m,m1,lt,ht; \
\
lt=l; \
ht=h; \
m =(bh)*(lt); \
lt=(bl)*(lt); \
m1=(bl)*(ht); \
ht =(bh)*(ht); \
- m=(m+m1)&BN_MASK2; if (m < m1) ht+=L2HBITS((BN_ULONG)1); \
+ m=(m+m1)&BN_MASK2; ht += L2HBITS((BN_ULONG)(m < m1)); \
ht+=HBITS(m); \
m1=L2HBITS(m); \
- lt=(lt+m1)&BN_MASK2; if (lt < m1) ht++; \
+ lt=(lt+m1)&BN_MASK2; ht += (lt < m1); \
(l)=lt; \
(h)=ht; \
}
# define sqr64(lo,ho,in) \
{ \
BN_ULONG l,h,m; \
\
h=(in); \
l=LBITS(h); \
h=HBITS(h); \
m =(l)*(h); \
l*=l; \
h*=h; \
h+=(m&BN_MASK2h1)>>(BN_BITS4-1); \
m =(m&BN_MASK2l)<<(BN_BITS4+1); \
- l=(l+m)&BN_MASK2; if (l < m) h++; \
+ l=(l+m)&BN_MASK2; h += (l < m); \
(lo)=l; \
(ho)=h; \
}
# define mul_add(r,a,bl,bh,c) { \
BN_ULONG l,h; \
\
h= (a); \
l=LBITS(h); \
h=HBITS(h); \
mul64(l,h,(bl),(bh)); \
\
/* non-multiply part */ \
- l=(l+(c))&BN_MASK2; if (l < (c)) h++; \
+ l=(l+(c))&BN_MASK2; h += (l < (c)); \
(c)=(r); \
- l=(l+(c))&BN_MASK2; if (l < (c)) h++; \
+ l=(l+(c))&BN_MASK2; h += (l < (c)); \
(c)=h&BN_MASK2; \
(r)=l; \
}
# define mul(r,a,bl,bh,c) { \
BN_ULONG l,h; \
\
h= (a); \
l=LBITS(h); \
h=HBITS(h); \
mul64(l,h,(bl),(bh)); \
\
/* non-multiply part */ \
- l+=(c); if ((l&BN_MASK2) < (c)) h++; \
+ l+=(c); h += ((l&BN_MASK2) < (c)); \
(c)=h&BN_MASK2; \
(r)=l&BN_MASK2; \
}
# endif /* !BN_LLONG */
void BN_RECP_CTX_init(BN_RECP_CTX *recp);
void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
void bn_init(BIGNUM *a);
void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb);
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp);
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a);
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a);
int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n);
int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl);
void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
int dna, int dnb, BN_ULONG *t);
void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b,
int n, int tna, int tnb, BN_ULONG *t);
void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t);
void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n);
void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
BN_ULONG *t);
BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
int cl, int dl);
int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
const BN_ULONG *np, const BN_ULONG *n0, int num);
-
+void bn_correct_top_consttime(BIGNUM *a);
BIGNUM *int_bn_mod_inverse(BIGNUM *in,
const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx,
int *noinv);
static ossl_inline BIGNUM *bn_expand(BIGNUM *a, int bits)
{
if (bits > (INT_MAX - BN_BITS2 + 1))
return NULL;
if (((bits+BN_BITS2-1)/BN_BITS2) <= (a)->dmax)
return a;
return bn_expand2((a),(bits+BN_BITS2-1)/BN_BITS2);
}
int ossl_bn_check_prime(const BIGNUM *w, int checks, BN_CTX *ctx,
int do_trial_division, BN_GENCB *cb);
#endif
diff --git a/crypto/bn/bn_nist.c b/crypto/bn/bn_nist.c
index da10c4054a3e..3d4d9a2fb2df 100644
--- a/crypto/bn/bn_nist.c
+++ b/crypto/bn/bn_nist.c
@@ -1,1250 +1,1215 @@
/*
- * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 "bn_local.h"
#include "internal/cryptlib.h"
#define BN_NIST_192_TOP (192+BN_BITS2-1)/BN_BITS2
#define BN_NIST_224_TOP (224+BN_BITS2-1)/BN_BITS2
#define BN_NIST_256_TOP (256+BN_BITS2-1)/BN_BITS2
#define BN_NIST_384_TOP (384+BN_BITS2-1)/BN_BITS2
#define BN_NIST_521_TOP (521+BN_BITS2-1)/BN_BITS2
/* pre-computed tables are "carry-less" values of modulus*(i+1) */
#if BN_BITS2 == 64
static const BN_ULONG _nist_p_192[][BN_NIST_192_TOP] = {
{0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFFULL},
{0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFFULL},
{0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFCULL, 0xFFFFFFFFFFFFFFFFULL}
};
static const BN_ULONG _nist_p_192_sqr[] = {
0x0000000000000001ULL, 0x0000000000000002ULL, 0x0000000000000001ULL,
0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFFULL
};
static const BN_ULONG _nist_p_224[][BN_NIST_224_TOP] = {
{0x0000000000000001ULL, 0xFFFFFFFF00000000ULL,
0xFFFFFFFFFFFFFFFFULL, 0x00000000FFFFFFFFULL},
{0x0000000000000002ULL, 0xFFFFFFFE00000000ULL,
0xFFFFFFFFFFFFFFFFULL, 0x00000001FFFFFFFFULL} /* this one is
* "carry-full" */
};
static const BN_ULONG _nist_p_224_sqr[] = {
0x0000000000000001ULL, 0xFFFFFFFE00000000ULL,
0xFFFFFFFFFFFFFFFFULL, 0x0000000200000000ULL,
0x0000000000000000ULL, 0xFFFFFFFFFFFFFFFEULL,
0xFFFFFFFFFFFFFFFFULL
};
static const BN_ULONG _nist_p_256[][BN_NIST_256_TOP] = {
{0xFFFFFFFFFFFFFFFFULL, 0x00000000FFFFFFFFULL,
0x0000000000000000ULL, 0xFFFFFFFF00000001ULL},
{0xFFFFFFFFFFFFFFFEULL, 0x00000001FFFFFFFFULL,
0x0000000000000000ULL, 0xFFFFFFFE00000002ULL},
{0xFFFFFFFFFFFFFFFDULL, 0x00000002FFFFFFFFULL,
0x0000000000000000ULL, 0xFFFFFFFD00000003ULL},
{0xFFFFFFFFFFFFFFFCULL, 0x00000003FFFFFFFFULL,
0x0000000000000000ULL, 0xFFFFFFFC00000004ULL},
{0xFFFFFFFFFFFFFFFBULL, 0x00000004FFFFFFFFULL,
0x0000000000000000ULL, 0xFFFFFFFB00000005ULL},
};
static const BN_ULONG _nist_p_256_sqr[] = {
0x0000000000000001ULL, 0xFFFFFFFE00000000ULL,
0xFFFFFFFFFFFFFFFFULL, 0x00000001FFFFFFFEULL,
0x00000001FFFFFFFEULL, 0x00000001FFFFFFFEULL,
0xFFFFFFFE00000001ULL, 0xFFFFFFFE00000002ULL
};
static const BN_ULONG _nist_p_384[][BN_NIST_384_TOP] = {
{0x00000000FFFFFFFFULL, 0xFFFFFFFF00000000ULL, 0xFFFFFFFFFFFFFFFEULL,
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL},
{0x00000001FFFFFFFEULL, 0xFFFFFFFE00000000ULL, 0xFFFFFFFFFFFFFFFDULL,
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL},
{0x00000002FFFFFFFDULL, 0xFFFFFFFD00000000ULL, 0xFFFFFFFFFFFFFFFCULL,
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL},
{0x00000003FFFFFFFCULL, 0xFFFFFFFC00000000ULL, 0xFFFFFFFFFFFFFFFBULL,
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL},
{0x00000004FFFFFFFBULL, 0xFFFFFFFB00000000ULL, 0xFFFFFFFFFFFFFFFAULL,
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL},
};
static const BN_ULONG _nist_p_384_sqr[] = {
0xFFFFFFFE00000001ULL, 0x0000000200000000ULL, 0xFFFFFFFE00000000ULL,
0x0000000200000000ULL, 0x0000000000000001ULL, 0x0000000000000000ULL,
0x00000001FFFFFFFEULL, 0xFFFFFFFE00000000ULL, 0xFFFFFFFFFFFFFFFDULL,
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL
};
static const BN_ULONG _nist_p_521[] =
{ 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,
0x00000000000001FFULL
};
static const BN_ULONG _nist_p_521_sqr[] = {
0x0000000000000001ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
0x0000000000000000ULL, 0x0000000000000000ULL, 0xFFFFFFFFFFFFFC00ULL,
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,
0xFFFFFFFFFFFFFFFFULL, 0x000000000003FFFFULL
};
#elif BN_BITS2 == 32
static const BN_ULONG _nist_p_192[][BN_NIST_192_TOP] = {
{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
{0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
{0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
};
static const BN_ULONG _nist_p_192_sqr[] = {
0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000001, 0x00000000,
0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
};
static const BN_ULONG _nist_p_224[][BN_NIST_224_TOP] = {
{0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
{0x00000002, 0x00000000, 0x00000000, 0xFFFFFFFE,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
};
static const BN_ULONG _nist_p_224_sqr[] = {
0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE,
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000002,
0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF
};
static const BN_ULONG _nist_p_256[][BN_NIST_256_TOP] = {
{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF},
{0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001,
0x00000000, 0x00000000, 0x00000002, 0xFFFFFFFE},
{0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000002,
0x00000000, 0x00000000, 0x00000003, 0xFFFFFFFD},
{0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000003,
0x00000000, 0x00000000, 0x00000004, 0xFFFFFFFC},
{0xFFFFFFFB, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000004,
0x00000000, 0x00000000, 0x00000005, 0xFFFFFFFB},
};
static const BN_ULONG _nist_p_256_sqr[] = {
0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001,
0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001,
0x00000001, 0xFFFFFFFE, 0x00000002, 0xFFFFFFFE
};
static const BN_ULONG _nist_p_384[][BN_NIST_384_TOP] = {
{0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
{0xFFFFFFFE, 0x00000001, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
{0xFFFFFFFD, 0x00000002, 0x00000000, 0xFFFFFFFD, 0xFFFFFFFC, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
{0xFFFFFFFC, 0x00000003, 0x00000000, 0xFFFFFFFC, 0xFFFFFFFB, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
{0xFFFFFFFB, 0x00000004, 0x00000000, 0xFFFFFFFB, 0xFFFFFFFA, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
};
static const BN_ULONG _nist_p_384_sqr[] = {
0x00000001, 0xFFFFFFFE, 0x00000000, 0x00000002, 0x00000000, 0xFFFFFFFE,
0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
0xFFFFFFFE, 0x00000001, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
};
static const BN_ULONG _nist_p_521[] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0x000001FF
};
static const BN_ULONG _nist_p_521_sqr[] = {
0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFC00, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0x0003FFFF
};
#else
# error "unsupported BN_BITS2"
#endif
static const BIGNUM ossl_bignum_nist_p_192 = {
(BN_ULONG *)_nist_p_192[0],
BN_NIST_192_TOP,
BN_NIST_192_TOP,
0,
BN_FLG_STATIC_DATA
};
static const BIGNUM ossl_bignum_nist_p_224 = {
(BN_ULONG *)_nist_p_224[0],
BN_NIST_224_TOP,
BN_NIST_224_TOP,
0,
BN_FLG_STATIC_DATA
};
static const BIGNUM ossl_bignum_nist_p_256 = {
(BN_ULONG *)_nist_p_256[0],
BN_NIST_256_TOP,
BN_NIST_256_TOP,
0,
BN_FLG_STATIC_DATA
};
static const BIGNUM ossl_bignum_nist_p_384 = {
(BN_ULONG *)_nist_p_384[0],
BN_NIST_384_TOP,
BN_NIST_384_TOP,
0,
BN_FLG_STATIC_DATA
};
static const BIGNUM ossl_bignum_nist_p_521 = {
(BN_ULONG *)_nist_p_521,
BN_NIST_521_TOP,
BN_NIST_521_TOP,
0,
BN_FLG_STATIC_DATA
};
const BIGNUM *BN_get0_nist_prime_192(void)
{
return &ossl_bignum_nist_p_192;
}
const BIGNUM *BN_get0_nist_prime_224(void)
{
return &ossl_bignum_nist_p_224;
}
const BIGNUM *BN_get0_nist_prime_256(void)
{
return &ossl_bignum_nist_p_256;
}
const BIGNUM *BN_get0_nist_prime_384(void)
{
return &ossl_bignum_nist_p_384;
}
const BIGNUM *BN_get0_nist_prime_521(void)
{
return &ossl_bignum_nist_p_521;
}
/*
* To avoid more recent compilers (specifically clang-14) from treating this
* code as a violation of the strict aliasing conditions and omiting it, this
* cannot be declared as a function. Moreover, the dst parameter cannot be
* cached in a local since this no longer references the union and again falls
* foul of the strict aliasing criteria. Refer to #18225 for the initial
* diagnostics and llvm/llvm-project#55255 for the later discussions with the
* LLVM developers. The problem boils down to if an array in the union is
* converted to a pointer or if it is used directly.
*
* This function was inlined regardless, so there is no space cost to be
* paid for making it a macro.
*/
#define nist_cp_bn_0(dst, src_in, top, max) \
{ \
int ii; \
const BN_ULONG *src = src_in; \
\
for (ii = 0; ii < top; ii++) \
(dst)[ii] = src[ii]; \
for (; ii < max; ii++) \
(dst)[ii] = 0; \
}
static void nist_cp_bn(BN_ULONG *dst, const BN_ULONG *src, int top)
{
int i;
for (i = 0; i < top; i++)
dst[i] = src[i];
}
#if BN_BITS2 == 64
# define bn_cp_64(to, n, from, m) (to)[n] = (m>=0)?((from)[m]):0;
# define bn_64_set_0(to, n) (to)[n] = (BN_ULONG)0;
/*
* two following macros are implemented under assumption that they
* are called in a sequence with *ascending* n, i.e. as they are...
*/
# define bn_cp_32_naked(to, n, from, m) (((n)&1)?(to[(n)/2]|=((m)&1)?(from[(m)/2]&BN_MASK2h):(from[(m)/2]<<32))\
:(to[(n)/2] =((m)&1)?(from[(m)/2]>>32):(from[(m)/2]&BN_MASK2l)))
# define bn_32_set_0(to, n) (((n)&1)?(to[(n)/2]&=BN_MASK2l):(to[(n)/2]=0));
# define bn_cp_32(to,n,from,m) ((m)>=0)?bn_cp_32_naked(to,n,from,m):bn_32_set_0(to,n)
# if defined(L_ENDIAN)
# if defined(__arch64__)
# define NIST_INT64 long
# else
# define NIST_INT64 long long
# endif
# endif
#else
# define bn_cp_64(to, n, from, m) \
{ \
bn_cp_32(to, (n)*2, from, (m)*2); \
bn_cp_32(to, (n)*2+1, from, (m)*2+1); \
}
# define bn_64_set_0(to, n) \
{ \
bn_32_set_0(to, (n)*2); \
bn_32_set_0(to, (n)*2+1); \
}
# define bn_cp_32(to, n, from, m) (to)[n] = (m>=0)?((from)[m]):0;
# define bn_32_set_0(to, n) (to)[n] = (BN_ULONG)0;
# if defined(_WIN32) && !defined(__GNUC__)
# define NIST_INT64 __int64
# elif defined(BN_LLONG)
# define NIST_INT64 long long
# endif
#endif /* BN_BITS2 != 64 */
#define nist_set_192(to, from, a1, a2, a3) \
{ \
bn_cp_64(to, 0, from, (a3) - 3) \
bn_cp_64(to, 1, from, (a2) - 3) \
bn_cp_64(to, 2, from, (a1) - 3) \
}
int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
BN_CTX *ctx)
{
int top = a->top, i;
int carry;
register BN_ULONG *r_d, *a_d = a->d;
union {
BN_ULONG bn[BN_NIST_192_TOP];
unsigned int ui[BN_NIST_192_TOP * sizeof(BN_ULONG) /
sizeof(unsigned int)];
} buf;
BN_ULONG c_d[BN_NIST_192_TOP], *res;
- PTR_SIZE_INT mask;
static const BIGNUM ossl_bignum_nist_p_192_sqr = {
(BN_ULONG *)_nist_p_192_sqr,
OSSL_NELEM(_nist_p_192_sqr),
OSSL_NELEM(_nist_p_192_sqr),
0, BN_FLG_STATIC_DATA
};
field = &ossl_bignum_nist_p_192; /* just to make sure */
if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_192_sqr) >= 0)
return BN_nnmod(r, a, field, ctx);
i = BN_ucmp(field, a);
if (i == 0) {
BN_zero(r);
return 1;
} else if (i > 0)
return (r == a) ? 1 : (BN_copy(r, a) != NULL);
if (r != a) {
if (!bn_wexpand(r, BN_NIST_192_TOP))
return 0;
r_d = r->d;
nist_cp_bn(r_d, a_d, BN_NIST_192_TOP);
} else
r_d = a_d;
nist_cp_bn_0(buf.bn, a_d + BN_NIST_192_TOP, top - BN_NIST_192_TOP,
BN_NIST_192_TOP);
#if defined(NIST_INT64)
{
NIST_INT64 acc; /* accumulator */
unsigned int *rp = (unsigned int *)r_d;
const unsigned int *bp = (const unsigned int *)buf.ui;
acc = rp[0];
acc += bp[3 * 2 - 6];
acc += bp[5 * 2 - 6];
rp[0] = (unsigned int)acc;
acc >>= 32;
acc += rp[1];
acc += bp[3 * 2 - 5];
acc += bp[5 * 2 - 5];
rp[1] = (unsigned int)acc;
acc >>= 32;
acc += rp[2];
acc += bp[3 * 2 - 6];
acc += bp[4 * 2 - 6];
acc += bp[5 * 2 - 6];
rp[2] = (unsigned int)acc;
acc >>= 32;
acc += rp[3];
acc += bp[3 * 2 - 5];
acc += bp[4 * 2 - 5];
acc += bp[5 * 2 - 5];
rp[3] = (unsigned int)acc;
acc >>= 32;
acc += rp[4];
acc += bp[4 * 2 - 6];
acc += bp[5 * 2 - 6];
rp[4] = (unsigned int)acc;
acc >>= 32;
acc += rp[5];
acc += bp[4 * 2 - 5];
acc += bp[5 * 2 - 5];
rp[5] = (unsigned int)acc;
carry = (int)(acc >> 32);
}
#else
{
BN_ULONG t_d[BN_NIST_192_TOP];
nist_set_192(t_d, buf.bn, 0, 3, 3);
carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
nist_set_192(t_d, buf.bn, 4, 4, 0);
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
nist_set_192(t_d, buf.bn, 5, 5, 5)
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
}
#endif
if (carry > 0)
carry =
(int)bn_sub_words(r_d, r_d, _nist_p_192[carry - 1],
BN_NIST_192_TOP);
else
carry = 1;
/*
* we need 'if (carry==0 || result>=modulus) result-=modulus;'
* as comparison implies subtraction, we can write
* 'tmp=result-modulus; if (!carry || !borrow) result=tmp;'
* this is what happens below, but without explicit if:-) a.
*/
- mask =
- 0 - (PTR_SIZE_INT) bn_sub_words(c_d, r_d, _nist_p_192[0],
- BN_NIST_192_TOP);
- mask &= 0 - (PTR_SIZE_INT) carry;
- res = c_d;
- res = (BN_ULONG *)
- (((PTR_SIZE_INT) res & ~mask) | ((PTR_SIZE_INT) r_d & mask));
+ res = (bn_sub_words(c_d, r_d, _nist_p_192[0], BN_NIST_192_TOP) && carry)
+ ? r_d
+ : c_d;
nist_cp_bn(r_d, res, BN_NIST_192_TOP);
r->top = BN_NIST_192_TOP;
bn_correct_top(r);
return 1;
}
typedef BN_ULONG (*bn_addsub_f) (BN_ULONG *, const BN_ULONG *,
const BN_ULONG *, int);
#define nist_set_224(to, from, a1, a2, a3, a4, a5, a6, a7) \
{ \
bn_cp_32(to, 0, from, (a7) - 7) \
bn_cp_32(to, 1, from, (a6) - 7) \
bn_cp_32(to, 2, from, (a5) - 7) \
bn_cp_32(to, 3, from, (a4) - 7) \
bn_cp_32(to, 4, from, (a3) - 7) \
bn_cp_32(to, 5, from, (a2) - 7) \
bn_cp_32(to, 6, from, (a1) - 7) \
}
int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
BN_CTX *ctx)
{
int top = a->top, i;
int carry;
BN_ULONG *r_d, *a_d = a->d;
union {
BN_ULONG bn[BN_NIST_224_TOP];
unsigned int ui[BN_NIST_224_TOP * sizeof(BN_ULONG) /
sizeof(unsigned int)];
} buf;
BN_ULONG c_d[BN_NIST_224_TOP], *res;
- PTR_SIZE_INT mask;
- union {
- bn_addsub_f f;
- PTR_SIZE_INT p;
- } u;
+ bn_addsub_f adjust;
static const BIGNUM ossl_bignum_nist_p_224_sqr = {
(BN_ULONG *)_nist_p_224_sqr,
OSSL_NELEM(_nist_p_224_sqr),
OSSL_NELEM(_nist_p_224_sqr),
0, BN_FLG_STATIC_DATA
};
field = &ossl_bignum_nist_p_224; /* just to make sure */
if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_224_sqr) >= 0)
return BN_nnmod(r, a, field, ctx);
i = BN_ucmp(field, a);
if (i == 0) {
BN_zero(r);
return 1;
} else if (i > 0)
return (r == a) ? 1 : (BN_copy(r, a) != NULL);
if (r != a) {
if (!bn_wexpand(r, BN_NIST_224_TOP))
return 0;
r_d = r->d;
nist_cp_bn(r_d, a_d, BN_NIST_224_TOP);
} else
r_d = a_d;
#if BN_BITS2==64
/* copy upper 256 bits of 448 bit number ... */
nist_cp_bn_0(c_d, a_d + (BN_NIST_224_TOP - 1),
top - (BN_NIST_224_TOP - 1), BN_NIST_224_TOP);
/* ... and right shift by 32 to obtain upper 224 bits */
nist_set_224(buf.bn, c_d, 14, 13, 12, 11, 10, 9, 8);
/* truncate lower part to 224 bits too */
r_d[BN_NIST_224_TOP - 1] &= BN_MASK2l;
#else
nist_cp_bn_0(buf.bn, a_d + BN_NIST_224_TOP, top - BN_NIST_224_TOP,
BN_NIST_224_TOP);
#endif
#if defined(NIST_INT64) && BN_BITS2!=64
{
NIST_INT64 acc; /* accumulator */
unsigned int *rp = (unsigned int *)r_d;
const unsigned int *bp = (const unsigned int *)buf.ui;
acc = rp[0];
acc -= bp[7 - 7];
acc -= bp[11 - 7];
rp[0] = (unsigned int)acc;
acc >>= 32;
acc += rp[1];
acc -= bp[8 - 7];
acc -= bp[12 - 7];
rp[1] = (unsigned int)acc;
acc >>= 32;
acc += rp[2];
acc -= bp[9 - 7];
acc -= bp[13 - 7];
rp[2] = (unsigned int)acc;
acc >>= 32;
acc += rp[3];
acc += bp[7 - 7];
acc += bp[11 - 7];
acc -= bp[10 - 7];
rp[3] = (unsigned int)acc;
acc >>= 32;
acc += rp[4];
acc += bp[8 - 7];
acc += bp[12 - 7];
acc -= bp[11 - 7];
rp[4] = (unsigned int)acc;
acc >>= 32;
acc += rp[5];
acc += bp[9 - 7];
acc += bp[13 - 7];
acc -= bp[12 - 7];
rp[5] = (unsigned int)acc;
acc >>= 32;
acc += rp[6];
acc += bp[10 - 7];
acc -= bp[13 - 7];
rp[6] = (unsigned int)acc;
carry = (int)(acc >> 32);
# if BN_BITS2==64
rp[7] = carry;
# endif
}
#else
{
BN_ULONG t_d[BN_NIST_224_TOP];
nist_set_224(t_d, buf.bn, 10, 9, 8, 7, 0, 0, 0);
carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP);
nist_set_224(t_d, buf.bn, 0, 13, 12, 11, 0, 0, 0);
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP);
nist_set_224(t_d, buf.bn, 13, 12, 11, 10, 9, 8, 7);
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP);
nist_set_224(t_d, buf.bn, 0, 0, 0, 0, 13, 12, 11);
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP);
# if BN_BITS2==64
carry = (int)(r_d[BN_NIST_224_TOP - 1] >> 32);
# endif
}
#endif
- u.f = bn_sub_words;
+ adjust = bn_sub_words;
if (carry > 0) {
carry =
(int)bn_sub_words(r_d, r_d, _nist_p_224[carry - 1],
BN_NIST_224_TOP);
#if BN_BITS2==64
carry = (int)(~(r_d[BN_NIST_224_TOP - 1] >> 32)) & 1;
#endif
} else if (carry < 0) {
/*
* it's a bit more complicated logic in this case. if bn_add_words
* yields no carry, then result has to be adjusted by unconditionally
* *adding* the modulus. but if it does, then result has to be
* compared to the modulus and conditionally adjusted by
* *subtracting* the latter.
*/
carry =
(int)bn_add_words(r_d, r_d, _nist_p_224[-carry - 1],
BN_NIST_224_TOP);
- mask = 0 - (PTR_SIZE_INT) carry;
- u.p = ((PTR_SIZE_INT) bn_sub_words & mask) |
- ((PTR_SIZE_INT) bn_add_words & ~mask);
+ adjust = carry ? bn_sub_words : bn_add_words;
} else
carry = 1;
/* otherwise it's effectively same as in BN_nist_mod_192... */
- mask =
- 0 - (PTR_SIZE_INT) (*u.f) (c_d, r_d, _nist_p_224[0], BN_NIST_224_TOP);
- mask &= 0 - (PTR_SIZE_INT) carry;
- res = c_d;
- res = (BN_ULONG *)(((PTR_SIZE_INT) res & ~mask) |
- ((PTR_SIZE_INT) r_d & mask));
+ res = ((*adjust) (c_d, r_d, _nist_p_224[0], BN_NIST_224_TOP) && carry)
+ ? r_d
+ : c_d;
nist_cp_bn(r_d, res, BN_NIST_224_TOP);
r->top = BN_NIST_224_TOP;
bn_correct_top(r);
return 1;
}
#define nist_set_256(to, from, a1, a2, a3, a4, a5, a6, a7, a8) \
{ \
bn_cp_32(to, 0, from, (a8) - 8) \
bn_cp_32(to, 1, from, (a7) - 8) \
bn_cp_32(to, 2, from, (a6) - 8) \
bn_cp_32(to, 3, from, (a5) - 8) \
bn_cp_32(to, 4, from, (a4) - 8) \
bn_cp_32(to, 5, from, (a3) - 8) \
bn_cp_32(to, 6, from, (a2) - 8) \
bn_cp_32(to, 7, from, (a1) - 8) \
}
int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
BN_CTX *ctx)
{
int i, top = a->top;
int carry = 0;
register BN_ULONG *a_d = a->d, *r_d;
union {
BN_ULONG bn[BN_NIST_256_TOP];
unsigned int ui[BN_NIST_256_TOP * sizeof(BN_ULONG) /
sizeof(unsigned int)];
} buf;
BN_ULONG c_d[BN_NIST_256_TOP], *res;
- PTR_SIZE_INT mask;
- union {
- bn_addsub_f f;
- PTR_SIZE_INT p;
- } u;
+ bn_addsub_f adjust;
static const BIGNUM ossl_bignum_nist_p_256_sqr = {
(BN_ULONG *)_nist_p_256_sqr,
OSSL_NELEM(_nist_p_256_sqr),
OSSL_NELEM(_nist_p_256_sqr),
0, BN_FLG_STATIC_DATA
};
field = &ossl_bignum_nist_p_256; /* just to make sure */
if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_256_sqr) >= 0)
return BN_nnmod(r, a, field, ctx);
i = BN_ucmp(field, a);
if (i == 0) {
BN_zero(r);
return 1;
} else if (i > 0)
return (r == a) ? 1 : (BN_copy(r, a) != NULL);
if (r != a) {
if (!bn_wexpand(r, BN_NIST_256_TOP))
return 0;
r_d = r->d;
nist_cp_bn(r_d, a_d, BN_NIST_256_TOP);
} else
r_d = a_d;
nist_cp_bn_0(buf.bn, a_d + BN_NIST_256_TOP, top - BN_NIST_256_TOP,
BN_NIST_256_TOP);
#if defined(NIST_INT64)
{
NIST_INT64 acc; /* accumulator */
unsigned int *rp = (unsigned int *)r_d;
const unsigned int *bp = (const unsigned int *)buf.ui;
acc = rp[0];
acc += bp[8 - 8];
acc += bp[9 - 8];
acc -= bp[11 - 8];
acc -= bp[12 - 8];
acc -= bp[13 - 8];
acc -= bp[14 - 8];
rp[0] = (unsigned int)acc;
acc >>= 32;
acc += rp[1];
acc += bp[9 - 8];
acc += bp[10 - 8];
acc -= bp[12 - 8];
acc -= bp[13 - 8];
acc -= bp[14 - 8];
acc -= bp[15 - 8];
rp[1] = (unsigned int)acc;
acc >>= 32;
acc += rp[2];
acc += bp[10 - 8];
acc += bp[11 - 8];
acc -= bp[13 - 8];
acc -= bp[14 - 8];
acc -= bp[15 - 8];
rp[2] = (unsigned int)acc;
acc >>= 32;
acc += rp[3];
acc += bp[11 - 8];
acc += bp[11 - 8];
acc += bp[12 - 8];
acc += bp[12 - 8];
acc += bp[13 - 8];
acc -= bp[15 - 8];
acc -= bp[8 - 8];
acc -= bp[9 - 8];
rp[3] = (unsigned int)acc;
acc >>= 32;
acc += rp[4];
acc += bp[12 - 8];
acc += bp[12 - 8];
acc += bp[13 - 8];
acc += bp[13 - 8];
acc += bp[14 - 8];
acc -= bp[9 - 8];
acc -= bp[10 - 8];
rp[4] = (unsigned int)acc;
acc >>= 32;
acc += rp[5];
acc += bp[13 - 8];
acc += bp[13 - 8];
acc += bp[14 - 8];
acc += bp[14 - 8];
acc += bp[15 - 8];
acc -= bp[10 - 8];
acc -= bp[11 - 8];
rp[5] = (unsigned int)acc;
acc >>= 32;
acc += rp[6];
acc += bp[14 - 8];
acc += bp[14 - 8];
acc += bp[15 - 8];
acc += bp[15 - 8];
acc += bp[14 - 8];
acc += bp[13 - 8];
acc -= bp[8 - 8];
acc -= bp[9 - 8];
rp[6] = (unsigned int)acc;
acc >>= 32;
acc += rp[7];
acc += bp[15 - 8];
acc += bp[15 - 8];
acc += bp[15 - 8];
acc += bp[8 - 8];
acc -= bp[10 - 8];
acc -= bp[11 - 8];
acc -= bp[12 - 8];
acc -= bp[13 - 8];
rp[7] = (unsigned int)acc;
carry = (int)(acc >> 32);
}
#else
{
BN_ULONG t_d[BN_NIST_256_TOP];
/*
* S1
*/
nist_set_256(t_d, buf.bn, 15, 14, 13, 12, 11, 0, 0, 0);
/*
* S2
*/
nist_set_256(c_d, buf.bn, 0, 15, 14, 13, 12, 0, 0, 0);
carry = (int)bn_add_words(t_d, t_d, c_d, BN_NIST_256_TOP);
/* left shift */
{
register BN_ULONG *ap, t, c;
ap = t_d;
c = 0;
for (i = BN_NIST_256_TOP; i != 0; --i) {
t = *ap;
*(ap++) = ((t << 1) | c) & BN_MASK2;
c = (t & BN_TBIT) ? 1 : 0;
}
carry <<= 1;
carry |= c;
}
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP);
/*
* S3
*/
nist_set_256(t_d, buf.bn, 15, 14, 0, 0, 0, 10, 9, 8);
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP);
/*
* S4
*/
nist_set_256(t_d, buf.bn, 8, 13, 15, 14, 13, 11, 10, 9);
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP);
/*
* D1
*/
nist_set_256(t_d, buf.bn, 10, 8, 0, 0, 0, 13, 12, 11);
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
/*
* D2
*/
nist_set_256(t_d, buf.bn, 11, 9, 0, 0, 15, 14, 13, 12);
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
/*
* D3
*/
nist_set_256(t_d, buf.bn, 12, 0, 10, 9, 8, 15, 14, 13);
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
/*
* D4
*/
nist_set_256(t_d, buf.bn, 13, 0, 11, 10, 9, 0, 15, 14);
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
}
#endif
/* see BN_nist_mod_224 for explanation */
- u.f = bn_sub_words;
+ adjust = bn_sub_words;
if (carry > 0)
carry =
(int)bn_sub_words(r_d, r_d, _nist_p_256[carry - 1],
BN_NIST_256_TOP);
else if (carry < 0) {
carry =
(int)bn_add_words(r_d, r_d, _nist_p_256[-carry - 1],
BN_NIST_256_TOP);
- mask = 0 - (PTR_SIZE_INT) carry;
- u.p = ((PTR_SIZE_INT) bn_sub_words & mask) |
- ((PTR_SIZE_INT) bn_add_words & ~mask);
+ adjust = carry ? bn_sub_words : bn_add_words;
} else
carry = 1;
- mask =
- 0 - (PTR_SIZE_INT) (*u.f) (c_d, r_d, _nist_p_256[0], BN_NIST_256_TOP);
- mask &= 0 - (PTR_SIZE_INT) carry;
- res = c_d;
- res = (BN_ULONG *)(((PTR_SIZE_INT) res & ~mask) |
- ((PTR_SIZE_INT) r_d & mask));
+ res = ((*adjust) (c_d, r_d, _nist_p_256[0], BN_NIST_256_TOP) && carry)
+ ? r_d
+ : c_d;
nist_cp_bn(r_d, res, BN_NIST_256_TOP);
r->top = BN_NIST_256_TOP;
bn_correct_top(r);
return 1;
}
#define nist_set_384(to,from,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) \
{ \
bn_cp_32(to, 0, from, (a12) - 12) \
bn_cp_32(to, 1, from, (a11) - 12) \
bn_cp_32(to, 2, from, (a10) - 12) \
bn_cp_32(to, 3, from, (a9) - 12) \
bn_cp_32(to, 4, from, (a8) - 12) \
bn_cp_32(to, 5, from, (a7) - 12) \
bn_cp_32(to, 6, from, (a6) - 12) \
bn_cp_32(to, 7, from, (a5) - 12) \
bn_cp_32(to, 8, from, (a4) - 12) \
bn_cp_32(to, 9, from, (a3) - 12) \
bn_cp_32(to, 10, from, (a2) - 12) \
bn_cp_32(to, 11, from, (a1) - 12) \
}
int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
BN_CTX *ctx)
{
int i, top = a->top;
int carry = 0;
register BN_ULONG *r_d, *a_d = a->d;
union {
BN_ULONG bn[BN_NIST_384_TOP];
unsigned int ui[BN_NIST_384_TOP * sizeof(BN_ULONG) /
sizeof(unsigned int)];
} buf;
BN_ULONG c_d[BN_NIST_384_TOP], *res;
- PTR_SIZE_INT mask;
- union {
- bn_addsub_f f;
- PTR_SIZE_INT p;
- } u;
+ bn_addsub_f adjust;
static const BIGNUM ossl_bignum_nist_p_384_sqr = {
(BN_ULONG *)_nist_p_384_sqr,
OSSL_NELEM(_nist_p_384_sqr),
OSSL_NELEM(_nist_p_384_sqr),
0, BN_FLG_STATIC_DATA
};
field = &ossl_bignum_nist_p_384; /* just to make sure */
if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_384_sqr) >= 0)
return BN_nnmod(r, a, field, ctx);
i = BN_ucmp(field, a);
if (i == 0) {
BN_zero(r);
return 1;
} else if (i > 0)
return (r == a) ? 1 : (BN_copy(r, a) != NULL);
if (r != a) {
if (!bn_wexpand(r, BN_NIST_384_TOP))
return 0;
r_d = r->d;
nist_cp_bn(r_d, a_d, BN_NIST_384_TOP);
} else
r_d = a_d;
nist_cp_bn_0(buf.bn, a_d + BN_NIST_384_TOP, top - BN_NIST_384_TOP,
BN_NIST_384_TOP);
#if defined(NIST_INT64)
{
NIST_INT64 acc; /* accumulator */
unsigned int *rp = (unsigned int *)r_d;
const unsigned int *bp = (const unsigned int *)buf.ui;
acc = rp[0];
acc += bp[12 - 12];
acc += bp[21 - 12];
acc += bp[20 - 12];
acc -= bp[23 - 12];
rp[0] = (unsigned int)acc;
acc >>= 32;
acc += rp[1];
acc += bp[13 - 12];
acc += bp[22 - 12];
acc += bp[23 - 12];
acc -= bp[12 - 12];
acc -= bp[20 - 12];
rp[1] = (unsigned int)acc;
acc >>= 32;
acc += rp[2];
acc += bp[14 - 12];
acc += bp[23 - 12];
acc -= bp[13 - 12];
acc -= bp[21 - 12];
rp[2] = (unsigned int)acc;
acc >>= 32;
acc += rp[3];
acc += bp[15 - 12];
acc += bp[12 - 12];
acc += bp[20 - 12];
acc += bp[21 - 12];
acc -= bp[14 - 12];
acc -= bp[22 - 12];
acc -= bp[23 - 12];
rp[3] = (unsigned int)acc;
acc >>= 32;
acc += rp[4];
acc += bp[21 - 12];
acc += bp[21 - 12];
acc += bp[16 - 12];
acc += bp[13 - 12];
acc += bp[12 - 12];
acc += bp[20 - 12];
acc += bp[22 - 12];
acc -= bp[15 - 12];
acc -= bp[23 - 12];
acc -= bp[23 - 12];
rp[4] = (unsigned int)acc;
acc >>= 32;
acc += rp[5];
acc += bp[22 - 12];
acc += bp[22 - 12];
acc += bp[17 - 12];
acc += bp[14 - 12];
acc += bp[13 - 12];
acc += bp[21 - 12];
acc += bp[23 - 12];
acc -= bp[16 - 12];
rp[5] = (unsigned int)acc;
acc >>= 32;
acc += rp[6];
acc += bp[23 - 12];
acc += bp[23 - 12];
acc += bp[18 - 12];
acc += bp[15 - 12];
acc += bp[14 - 12];
acc += bp[22 - 12];
acc -= bp[17 - 12];
rp[6] = (unsigned int)acc;
acc >>= 32;
acc += rp[7];
acc += bp[19 - 12];
acc += bp[16 - 12];
acc += bp[15 - 12];
acc += bp[23 - 12];
acc -= bp[18 - 12];
rp[7] = (unsigned int)acc;
acc >>= 32;
acc += rp[8];
acc += bp[20 - 12];
acc += bp[17 - 12];
acc += bp[16 - 12];
acc -= bp[19 - 12];
rp[8] = (unsigned int)acc;
acc >>= 32;
acc += rp[9];
acc += bp[21 - 12];
acc += bp[18 - 12];
acc += bp[17 - 12];
acc -= bp[20 - 12];
rp[9] = (unsigned int)acc;
acc >>= 32;
acc += rp[10];
acc += bp[22 - 12];
acc += bp[19 - 12];
acc += bp[18 - 12];
acc -= bp[21 - 12];
rp[10] = (unsigned int)acc;
acc >>= 32;
acc += rp[11];
acc += bp[23 - 12];
acc += bp[20 - 12];
acc += bp[19 - 12];
acc -= bp[22 - 12];
rp[11] = (unsigned int)acc;
carry = (int)(acc >> 32);
}
#else
{
BN_ULONG t_d[BN_NIST_384_TOP];
/*
* S1
*/
nist_set_256(t_d, buf.bn, 0, 0, 0, 0, 0, 23 - 4, 22 - 4, 21 - 4);
/* left shift */
{
register BN_ULONG *ap, t, c;
ap = t_d;
c = 0;
for (i = 3; i != 0; --i) {
t = *ap;
*(ap++) = ((t << 1) | c) & BN_MASK2;
c = (t & BN_TBIT) ? 1 : 0;
}
*ap = c;
}
carry =
(int)bn_add_words(r_d + (128 / BN_BITS2), r_d + (128 / BN_BITS2),
t_d, BN_NIST_256_TOP);
/*
* S2
*/
carry += (int)bn_add_words(r_d, r_d, buf.bn, BN_NIST_384_TOP);
/*
* S3
*/
nist_set_384(t_d, buf.bn, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22,
21);
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
/*
* S4
*/
nist_set_384(t_d, buf.bn, 19, 18, 17, 16, 15, 14, 13, 12, 20, 0, 23,
0);
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
/*
* S5
*/
nist_set_384(t_d, buf.bn, 0, 0, 0, 0, 23, 22, 21, 20, 0, 0, 0, 0);
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
/*
* S6
*/
nist_set_384(t_d, buf.bn, 0, 0, 0, 0, 0, 0, 23, 22, 21, 0, 0, 20);
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
/*
* D1
*/
nist_set_384(t_d, buf.bn, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12,
23);
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP);
/*
* D2
*/
nist_set_384(t_d, buf.bn, 0, 0, 0, 0, 0, 0, 0, 23, 22, 21, 20, 0);
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP);
/*
* D3
*/
nist_set_384(t_d, buf.bn, 0, 0, 0, 0, 0, 0, 0, 23, 23, 0, 0, 0);
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP);
}
#endif
/* see BN_nist_mod_224 for explanation */
- u.f = bn_sub_words;
+ adjust = bn_sub_words;
if (carry > 0)
carry =
(int)bn_sub_words(r_d, r_d, _nist_p_384[carry - 1],
BN_NIST_384_TOP);
else if (carry < 0) {
carry =
(int)bn_add_words(r_d, r_d, _nist_p_384[-carry - 1],
BN_NIST_384_TOP);
- mask = 0 - (PTR_SIZE_INT) carry;
- u.p = ((PTR_SIZE_INT) bn_sub_words & mask) |
- ((PTR_SIZE_INT) bn_add_words & ~mask);
+ adjust = carry ? bn_sub_words : bn_add_words;
} else
carry = 1;
- mask =
- 0 - (PTR_SIZE_INT) (*u.f) (c_d, r_d, _nist_p_384[0], BN_NIST_384_TOP);
- mask &= 0 - (PTR_SIZE_INT) carry;
- res = c_d;
- res = (BN_ULONG *)(((PTR_SIZE_INT) res & ~mask) |
- ((PTR_SIZE_INT) r_d & mask));
+ res = ((*adjust) (c_d, r_d, _nist_p_384[0], BN_NIST_384_TOP) && carry)
+ ? r_d
+ : c_d;
nist_cp_bn(r_d, res, BN_NIST_384_TOP);
r->top = BN_NIST_384_TOP;
bn_correct_top(r);
return 1;
}
#define BN_NIST_521_RSHIFT (521%BN_BITS2)
#define BN_NIST_521_LSHIFT (BN_BITS2-BN_NIST_521_RSHIFT)
#define BN_NIST_521_TOP_MASK ((BN_ULONG)BN_MASK2>>BN_NIST_521_LSHIFT)
int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
BN_CTX *ctx)
{
int top = a->top, i;
BN_ULONG *r_d, *a_d = a->d, t_d[BN_NIST_521_TOP], val, tmp, *res;
- PTR_SIZE_INT mask;
static const BIGNUM ossl_bignum_nist_p_521_sqr = {
(BN_ULONG *)_nist_p_521_sqr,
OSSL_NELEM(_nist_p_521_sqr),
OSSL_NELEM(_nist_p_521_sqr),
0, BN_FLG_STATIC_DATA
};
field = &ossl_bignum_nist_p_521; /* just to make sure */
if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_521_sqr) >= 0)
return BN_nnmod(r, a, field, ctx);
i = BN_ucmp(field, a);
if (i == 0) {
BN_zero(r);
return 1;
} else if (i > 0)
return (r == a) ? 1 : (BN_copy(r, a) != NULL);
if (r != a) {
if (!bn_wexpand(r, BN_NIST_521_TOP))
return 0;
r_d = r->d;
nist_cp_bn(r_d, a_d, BN_NIST_521_TOP);
} else
r_d = a_d;
/* upper 521 bits, copy ... */
nist_cp_bn_0(t_d, a_d + (BN_NIST_521_TOP - 1),
top - (BN_NIST_521_TOP - 1), BN_NIST_521_TOP);
/* ... and right shift */
for (val = t_d[0], i = 0; i < BN_NIST_521_TOP - 1; i++) {
#if 0
/*
* MSC ARM compiler [version 2013, presumably even earlier,
* much earlier] miscompiles this code, but not one in
* #else section. See RT#3541.
*/
tmp = val >> BN_NIST_521_RSHIFT;
val = t_d[i + 1];
t_d[i] = (tmp | val << BN_NIST_521_LSHIFT) & BN_MASK2;
#else
t_d[i] = (val >> BN_NIST_521_RSHIFT |
(tmp = t_d[i + 1]) << BN_NIST_521_LSHIFT) & BN_MASK2;
val = tmp;
#endif
}
t_d[i] = val >> BN_NIST_521_RSHIFT;
/* lower 521 bits */
r_d[i] &= BN_NIST_521_TOP_MASK;
bn_add_words(r_d, r_d, t_d, BN_NIST_521_TOP);
- mask =
- 0 - (PTR_SIZE_INT) bn_sub_words(t_d, r_d, _nist_p_521,
- BN_NIST_521_TOP);
- res = t_d;
- res = (BN_ULONG *)(((PTR_SIZE_INT) res & ~mask) |
- ((PTR_SIZE_INT) r_d & mask));
+ res = bn_sub_words(t_d, r_d, _nist_p_521,
+ BN_NIST_521_TOP)
+ ? r_d
+ : t_d;
nist_cp_bn(r_d, res, BN_NIST_521_TOP);
r->top = BN_NIST_521_TOP;
bn_correct_top(r);
return 1;
}
int (*BN_nist_mod_func(const BIGNUM *p)) (BIGNUM *r, const BIGNUM *a,
const BIGNUM *field, BN_CTX *ctx) {
if (BN_ucmp(&ossl_bignum_nist_p_192, p) == 0)
return BN_nist_mod_192;
if (BN_ucmp(&ossl_bignum_nist_p_224, p) == 0)
return BN_nist_mod_224;
if (BN_ucmp(&ossl_bignum_nist_p_256, p) == 0)
return BN_nist_mod_256;
if (BN_ucmp(&ossl_bignum_nist_p_384, p) == 0)
return BN_nist_mod_384;
if (BN_ucmp(&ossl_bignum_nist_p_521, p) == 0)
return BN_nist_mod_521;
return 0;
}
diff --git a/crypto/bn/bn_rsa_fips186_4.c b/crypto/bn/bn_rsa_fips186_4.c
index abce1aa2d830..62d8685d03e0 100644
--- a/crypto/bn/bn_rsa_fips186_4.c
+++ b/crypto/bn/bn_rsa_fips186_4.c
@@ -1,367 +1,367 @@
/*
- * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018-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
*/
/*
* According to NIST SP800-131A "Transitioning the use of cryptographic
* algorithms and key lengths" Generation of 1024 bit RSA keys are no longer
* allowed for signatures (Table 2) or key transport (Table 5). In the code
* below any attempt to generate 1024 bit RSA keys will result in an error (Note
* that digital signature verification can still use deprecated 1024 bit keys).
*
* FIPS 186-4 relies on the use of the auxiliary primes p1, p2, q1 and q2 that
* must be generated before the module generates the RSA primes p and q.
* Table B.1 in FIPS 186-4 specifies RSA modulus lengths of 2048 and
* 3072 bits only, the min/max total length of the auxiliary primes.
* FIPS 186-5 Table A.1 includes an additional entry for 4096 which has been
* included here.
*/
#include <stdio.h>
#include <openssl/bn.h>
#include "bn_local.h"
#include "crypto/bn.h"
#include "internal/nelem.h"
#if BN_BITS2 == 64
# define BN_DEF(lo, hi) (BN_ULONG)hi<<32|lo
#else
# define BN_DEF(lo, hi) lo, hi
#endif
/* 1 / sqrt(2) * 2^256, rounded up */
static const BN_ULONG inv_sqrt_2_val[] = {
BN_DEF(0x83339916UL, 0xED17AC85UL), BN_DEF(0x893BA84CUL, 0x1D6F60BAUL),
BN_DEF(0x754ABE9FUL, 0x597D89B3UL), BN_DEF(0xF9DE6484UL, 0xB504F333UL)
};
const BIGNUM ossl_bn_inv_sqrt_2 = {
(BN_ULONG *)inv_sqrt_2_val,
OSSL_NELEM(inv_sqrt_2_val),
OSSL_NELEM(inv_sqrt_2_val),
0,
BN_FLG_STATIC_DATA
};
/*
* FIPS 186-5 Table A.1. "Min length of auxiliary primes p1, p2, q1, q2".
* (FIPS 186-5 has an entry for >= 4096 bits).
*
* Params:
* nbits The key size in bits.
* Returns:
* The minimum size of the auxiliary primes or 0 if nbits is invalid.
*/
static int bn_rsa_fips186_5_aux_prime_min_size(int nbits)
{
if (nbits >= 4096)
return 201;
if (nbits >= 3072)
return 171;
if (nbits >= 2048)
return 141;
return 0;
}
/*
* FIPS 186-5 Table A.1 "Max of len(p1) + len(p2) and
* len(q1) + len(q2) for p,q Probable Primes".
* (FIPS 186-5 has an entry for >= 4096 bits).
* Params:
* nbits The key size in bits.
* Returns:
* The maximum length or 0 if nbits is invalid.
*/
static int bn_rsa_fips186_5_aux_prime_max_sum_size_for_prob_primes(int nbits)
{
if (nbits >= 4096)
return 2030;
if (nbits >= 3072)
return 1518;
if (nbits >= 2048)
return 1007;
return 0;
}
/*
* Find the first odd integer that is a probable prime.
*
* See section FIPS 186-4 B.3.6 (Steps 4.2/5.2).
*
* Params:
* Xp1 The passed in starting point to find a probably prime.
* p1 The returned probable prime (first odd integer >= Xp1)
* ctx A BN_CTX object.
* cb An optional BIGNUM callback.
* Returns: 1 on success otherwise it returns 0.
*/
static int bn_rsa_fips186_4_find_aux_prob_prime(const BIGNUM *Xp1,
BIGNUM *p1, BN_CTX *ctx,
BN_GENCB *cb)
{
int ret = 0;
int i = 0;
int tmp = 0;
if (BN_copy(p1, Xp1) == NULL)
return 0;
BN_set_flags(p1, BN_FLG_CONSTTIME);
/* Find the first odd number >= Xp1 that is probably prime */
for(;;) {
i++;
BN_GENCB_call(cb, 0, i);
/* MR test with trial division */
tmp = BN_check_prime(p1, ctx, cb);
if (tmp > 0)
break;
if (tmp < 0)
goto err;
/* Get next odd number */
if (!BN_add_word(p1, 2))
goto err;
}
BN_GENCB_call(cb, 2, i);
ret = 1;
err:
return ret;
}
/*
* Generate a probable prime (p or q).
*
* See FIPS 186-4 B.3.6 (Steps 4 & 5)
*
* Params:
* p The returned probable prime.
* Xpout An optionally returned random number used during generation of p.
* p1, p2 The returned auxiliary primes. If NULL they are not returned.
* Xp An optional passed in value (that is random number used during
* generation of p).
* Xp1, Xp2 Optional passed in values that are normally generated
* internally. Used to find p1, p2.
* nlen The bit length of the modulus (the key size).
* e The public exponent.
* ctx A BN_CTX object.
* cb An optional BIGNUM callback.
* Returns: 1 on success otherwise it returns 0.
*/
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 ret = 0;
BIGNUM *p1i = NULL, *p2i = NULL, *Xp1i = NULL, *Xp2i = NULL;
int bitlen;
if (p == NULL || Xpout == NULL)
return 0;
BN_CTX_start(ctx);
p1i = (p1 != NULL) ? p1 : BN_CTX_get(ctx);
p2i = (p2 != NULL) ? p2 : BN_CTX_get(ctx);
Xp1i = (Xp1 != NULL) ? (BIGNUM *)Xp1 : BN_CTX_get(ctx);
Xp2i = (Xp2 != NULL) ? (BIGNUM *)Xp2 : BN_CTX_get(ctx);
if (p1i == NULL || p2i == NULL || Xp1i == NULL || Xp2i == NULL)
goto err;
bitlen = bn_rsa_fips186_5_aux_prime_min_size(nlen);
if (bitlen == 0)
goto err;
/* (Steps 4.1/5.1): Randomly generate Xp1 if it is not passed in */
if (Xp1 == NULL) {
/* Set the top and bottom bits to make it odd and the correct size */
if (!BN_priv_rand_ex(Xp1i, bitlen, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD,
0, ctx))
goto err;
}
/* (Steps 4.1/5.1): Randomly generate Xp2 if it is not passed in */
if (Xp2 == NULL) {
/* Set the top and bottom bits to make it odd and the correct size */
if (!BN_priv_rand_ex(Xp2i, bitlen, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD,
0, ctx))
goto err;
}
/* (Steps 4.2/5.2) - find first auxiliary probable primes */
if (!bn_rsa_fips186_4_find_aux_prob_prime(Xp1i, p1i, ctx, cb)
|| !bn_rsa_fips186_4_find_aux_prob_prime(Xp2i, p2i, ctx, cb))
goto err;
/* (Table B.1) auxiliary prime Max length check */
if ((BN_num_bits(p1i) + BN_num_bits(p2i)) >=
bn_rsa_fips186_5_aux_prime_max_sum_size_for_prob_primes(nlen))
goto err;
/* (Steps 4.3/5.3) - generate prime */
if (!ossl_bn_rsa_fips186_4_derive_prime(p, Xpout, Xp, p1i, p2i, nlen, e,
ctx, cb))
goto err;
ret = 1;
err:
/* Zeroize any internally generated values that are not returned */
if (p1 == NULL)
BN_clear(p1i);
if (p2 == NULL)
BN_clear(p2i);
if (Xp1 == NULL)
BN_clear(Xp1i);
if (Xp2 == NULL)
BN_clear(Xp2i);
BN_CTX_end(ctx);
return ret;
}
/*
* Constructs a probable prime (a candidate for p or q) using 2 auxiliary
* prime numbers and the Chinese Remainder Theorem.
*
* See FIPS 186-4 C.9 "Compute a Probable Prime Factor Based on Auxiliary
* Primes". Used by FIPS 186-4 B.3.6 Section (4.3) for p and Section (5.3) for q.
*
* Params:
* Y The returned prime factor (private_prime_factor) of the modulus n.
* X The returned random number used during generation of the prime factor.
* Xin An optional passed in value for X used for testing purposes.
* r1 An auxiliary prime.
* r2 An auxiliary prime.
* nlen The desired length of n (the RSA modulus).
* e The public exponent.
* ctx A BN_CTX object.
* cb An optional BIGNUM callback object.
* Returns: 1 on success otherwise it returns 0.
* Assumptions:
* Y, X, r1, r2, e are not NULL.
*/
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)
{
int ret = 0;
int i, imax;
int bits = nlen >> 1;
BIGNUM *tmp, *R, *r1r2x2, *y1, *r1x2;
BIGNUM *base, *range;
BN_CTX_start(ctx);
base = BN_CTX_get(ctx);
range = BN_CTX_get(ctx);
R = BN_CTX_get(ctx);
tmp = BN_CTX_get(ctx);
r1r2x2 = BN_CTX_get(ctx);
y1 = BN_CTX_get(ctx);
r1x2 = BN_CTX_get(ctx);
if (r1x2 == NULL)
goto err;
if (Xin != NULL && BN_copy(X, Xin) == NULL)
goto err;
/*
* We need to generate a random number X in the range
* 1/sqrt(2) * 2^(nlen/2) <= X < 2^(nlen/2).
* We can rewrite that as:
* base = 1/sqrt(2) * 2^(nlen/2)
* range = ((2^(nlen/2))) - (1/sqrt(2) * 2^(nlen/2))
* X = base + random(range)
* We only have the first 256 bit of 1/sqrt(2)
*/
if (Xin == NULL) {
if (bits < BN_num_bits(&ossl_bn_inv_sqrt_2))
goto err;
if (!BN_lshift(base, &ossl_bn_inv_sqrt_2,
bits - BN_num_bits(&ossl_bn_inv_sqrt_2))
|| !BN_lshift(range, BN_value_one(), bits)
|| !BN_sub(range, range, base))
goto err;
}
if (!(BN_lshift1(r1x2, r1)
/* (Step 1) GCD(2r1, r2) = 1 */
&& BN_gcd(tmp, r1x2, r2, ctx)
&& BN_is_one(tmp)
/* (Step 2) R = ((r2^-1 mod 2r1) * r2) - ((2r1^-1 mod r2)*2r1) */
&& BN_mod_inverse(R, r2, r1x2, ctx)
&& BN_mul(R, R, r2, ctx) /* R = (r2^-1 mod 2r1) * r2 */
&& BN_mod_inverse(tmp, r1x2, r2, ctx)
&& BN_mul(tmp, tmp, r1x2, ctx) /* tmp = (2r1^-1 mod r2)*2r1 */
&& BN_sub(R, R, tmp)
/* Calculate 2r1r2 */
&& BN_mul(r1r2x2, r1x2, r2, ctx)))
goto err;
/* Make positive by adding the modulus */
if (BN_is_negative(R) && !BN_add(R, R, r1r2x2))
goto err;
/*
* In FIPS 186-4 imax was set to 5 * nlen/2.
* Analysis by Allen Roginsky (See https://csrc.nist.gov/CSRC/media/Publications/fips/186/4/final/documents/comments-received-fips186-4-december-2015.pdf
* page 68) indicates this has a 1 in 2 million chance of failure.
* The number has been updated to 20 * nlen/2 as used in
* FIPS186-5 Appendix B.9 Step 9.
*/
imax = 20 * bits; /* max = 20/2 * nbits */
for (;;) {
if (Xin == NULL) {
/*
* (Step 3) Choose Random X such that
* sqrt(2) * 2^(nlen/2-1) <= Random X <= (2^(nlen/2)) - 1.
*/
if (!BN_priv_rand_range_ex(X, range, 0, ctx) || !BN_add(X, X, base))
- goto end;
+ goto err;
}
/* (Step 4) Y = X + ((R - X) mod 2r1r2) */
if (!BN_mod_sub(Y, R, X, r1r2x2, ctx) || !BN_add(Y, Y, X))
goto err;
/* (Step 5) */
i = 0;
for (;;) {
/* (Step 6) */
if (BN_num_bits(Y) > bits) {
if (Xin == NULL)
break; /* Randomly Generated X so Go back to Step 3 */
else
goto err; /* X is not random so it will always fail */
}
BN_GENCB_call(cb, 0, 2);
/* (Step 7) If GCD(Y-1) == 1 & Y is probably prime then return Y */
if (BN_copy(y1, Y) == NULL
|| !BN_sub_word(y1, 1)
|| !BN_gcd(tmp, y1, e, ctx))
goto err;
if (BN_is_one(tmp)) {
int rv = BN_check_prime(Y, ctx, cb);
if (rv > 0)
goto end;
if (rv < 0)
goto err;
}
/* (Step 8-10) */
if (++i >= imax) {
ERR_raise(ERR_LIB_BN, BN_R_NO_PRIME_CANDIDATE);
goto err;
}
if (!BN_add(Y, Y, r1r2x2))
goto err;
}
}
end:
ret = 1;
BN_GENCB_call(cb, 3, 0);
err:
BN_clear(y1);
BN_CTX_end(ctx);
return ret;
}
diff --git a/crypto/bn/build.info b/crypto/bn/build.info
index f4ff6192393e..c4ba51b26552 100644
--- a/crypto/bn/build.info
+++ b/crypto/bn/build.info
@@ -1,177 +1,177 @@
LIBS=../../libcrypto
$BNASM=bn_asm.c
IF[{- !$disabled{asm} -}]
# Define source files and macros per asm architecture
# Known macros are:
#
# OPENSSL_BN_ASM_PART_WORDS For any collection with /-586/ file names
# OPENSSL_BN_ASM_MONT For any collection with /-mont/ file names
# OPENSSL_BN_ASM_MONT5 For any collection with /-mont5/ file names
# OPENSSL_BN_ASM_GF2m For any collection with /-gf2m/ file names
# OPENSSL_IA32_SSE2 For any collection with /86/ file names
# when sse2 is enabled
# BN_DIV3W For any collection with /-div3w/ file names
#
# All variables are named in such a way that they can be "indexed" with
# $target{asm_arch}
$BNASM_x86=bn-586.S co-586.S x86-mont.S x86-gf2m.S
# bn-586 is the only one implementing bn_*_part_words
# => OPENSSL_BN_ASM_PART_WORDS
$BNDEF_x86=OPENSSL_BN_ASM_PART_WORDS OPENSSL_BN_ASM_MONT OPENSSL_BN_ASM_GF2m
$BNDEF_x86_sse2=OPENSSL_IA32_SSE2
$BNASM_x86_64=\
x86_64-mont.s x86_64-mont5.s x86_64-gf2m.s rsaz_exp.c rsaz-x86_64.s \
rsaz-avx2.s rsaz_exp_x2.c rsaz-avx512.s
IF[{- $config{target} !~ /^VC/ -}]
$BNASM_x86_64=asm/x86_64-gcc.c $BNASM_x86_64
ELSE
$BNASM_x86_64=bn_asm.c $BNASM_x86_64
ENDIF
$BNDEF_x86_64=OPENSSL_BN_ASM_MONT OPENSSL_BN_ASM_MONT5 OPENSSL_BN_ASM_GF2m
$BNDEF_x86_64_sse2=OPENSSL_IA32_SSE2
IF[{- $config{target} !~ /^VC/ -}]
$BNASM_ia64=bn-ia64.s ia64-mont.s
ELSE
$BNASM_ia64=bn_asm.c ia64-mont.s
ENDIF
$BNASM_sparcv9=asm/sparcv8plus.S sparcv9-mont.S sparcv9a-mont.S vis3-mont.S \
sparct4-mont.S bn_sparc.c
$BNDEF_sparcv9=OPENSSL_BN_ASM_MONT
$BNASM_sparcv9_ec2m=sparcv9-gf2m.S
$BNDEF_sparcv9_ec2m=OPENSSL_BN_ASM_GF2m
$BNASM_sparcv8=asm/sparcv8.S
$BNASM_alpha=bn_asm.c alpha-mont.S
$BNDEF_alpha=OPENSSL_BN_ASM_MONT
$BNASM_mips32=bn-mips.S mips-mont.S
$BNDEF_mips32=OPENSSL_BN_ASM_MONT
$BNASM_mips64=$BNASM_mips32
$BNDEF_mips64=$BNDEF_mips32
IF[{- ($target{perlasm_scheme} // '') eq '31' -}]
$BNASM_s390x=bn_asm.c s390x-mont.S
ELSE
$BNASM_s390x=asm/s390x.S s390x-mont.S
ENDIF
$BNDEF_s390x=OPENSSL_BN_ASM_MONT
$BNASM_s390x_ec2m=s390x-gf2m.s
$BNDEF_s390x_ec2m=OPENSSL_BN_ASM_GF2m
$BNASM_armv4=bn_asm.c armv4-mont.S
$BNDEF_armv4=OPENSSL_BN_ASM_MONT
$BNASM_armv4_ec2m=armv4-gf2m.S
$BNDEF_armv4_ec2m=OPENSSL_BN_ASM_GF2m
$BNASM_aarch64=bn_asm.c armv8-mont.S
$BNDEF_aarch64=OPENSSL_BN_ASM_MONT
$BNASM_parisc11=bn_asm.c parisc-mont.s
$BNDEF_parisc11=OPENSSL_BN_ASM_MONT
$BNASM_parisc20_64=$BNASM_parisc11
$BNDEF_parisc20_64=$BNDEF_parisc11
$BNASM_ppc32=bn_ppc.c bn-ppc.s ppc-mont.s
$BNDEF_ppc32=OPENSSL_BN_ASM_MONT
$BNASM_ppc64=$BNASM_ppc32
$BNDEF_ppc64=$BNDEF_ppc32
$BNASM_c64xplus=asm/bn-c64xplus.asm
$BNASM_c64xplus_ec2m=c64xplus-gf2m.s
$BNDEF_c64xplus_ec2m=OPENSSL_BN_ASM_GF2m
# Now that we have defined all the arch specific variables, use the
# appropriate ones, and define the appropriate macros
IF[$BNASM_{- $target{asm_arch} -}]
$BNASM=$BNASM_{- $target{asm_arch} -}
$BNDEF=$BNDEF_{- $target{asm_arch} -}
IF[{- !$disabled{ec2m} -}]
$BNASM=$BNASM $BNASM_{- $target{asm_arch} -}_ec2m
$BNDEF=$BNDEF $BNDEF_{- $target{asm_arch} -}_ec2m
ENDIF
IF[{- !$disabled{sse2} -}]
$BNDEF=$BNDEF $BNDEF_{- $target{asm_arch} -}_sse2
ENDIF
ENDIF
ENDIF
$COMMON=bn_add.c bn_div.c bn_exp.c bn_lib.c bn_ctx.c bn_mul.c \
bn_mod.c bn_conv.c bn_rand.c bn_shift.c bn_word.c bn_blind.c \
bn_kron.c bn_sqrt.c bn_gcd.c bn_prime.c bn_sqr.c \
bn_recp.c bn_mont.c bn_mpi.c bn_exp2.c bn_gf2m.c bn_nist.c \
- bn_intern.c bn_dh.c bn_rsa_fips186_4.c bn_const.c rsa_sup_mul.c
+ bn_intern.c bn_dh.c bn_rsa_fips186_4.c bn_const.c
SOURCE[../../libcrypto]=$COMMON $BNASM bn_print.c bn_err.c bn_srp.c
DEFINE[../../libcrypto]=$BNDEF
IF[{- !$disabled{'deprecated-0.9.8'} -}]
SOURCE[../../libcrypto]=bn_depr.c
ENDIF
IF[{- !$disabled{'deprecated-3.0'} -}]
SOURCE[../../libcrypto]=bn_x931p.c
ENDIF
SOURCE[../../providers/libfips.a]=$COMMON $BNASM
DEFINE[../../providers/libfips.a]=$BNDEF
# Implementations are now spread across several libraries, so the defines
# need to be applied to all affected libraries and modules.
DEFINE[../../providers/libcommon.a]=$BNDEF
INCLUDE[bn_exp.o]=..
GENERATE[bn-586.S]=asm/bn-586.pl
DEPEND[bn-586.S]=../perlasm/x86asm.pl
GENERATE[co-586.S]=asm/co-586.pl
DEPEND[co-586.S]=../perlasm/x86asm.pl
GENERATE[x86-mont.S]=asm/x86-mont.pl
DEPEND[x86-mont.S]=../perlasm/x86asm.pl
GENERATE[x86-gf2m.S]=asm/x86-gf2m.pl
DEPEND[x86-gf2m.S]=../perlasm/x86asm.pl
GENERATE[sparcv9a-mont.S]=asm/sparcv9a-mont.pl
INCLUDE[sparcv9a-mont.o]=..
GENERATE[sparcv9-mont.S]=asm/sparcv9-mont.pl
INCLUDE[sparcv9-mont.o]=..
GENERATE[vis3-mont.S]=asm/vis3-mont.pl
INCLUDE[vis3-mont.o]=..
GENERATE[sparct4-mont.S]=asm/sparct4-mont.pl
INCLUDE[sparct4-mont.o]=..
GENERATE[sparcv9-gf2m.S]=asm/sparcv9-gf2m.pl
INCLUDE[sparcv9-gf2m.o]=..
GENERATE[bn-mips.S]=asm/mips.pl
INCLUDE[bn-mips.o]=..
GENERATE[mips-mont.S]=asm/mips-mont.pl
INCLUDE[mips-mont.o]=..
GENERATE[s390x-mont.S]=asm/s390x-mont.pl
GENERATE[s390x-gf2m.s]=asm/s390x-gf2m.pl
GENERATE[x86_64-mont.s]=asm/x86_64-mont.pl
GENERATE[x86_64-mont5.s]=asm/x86_64-mont5.pl
GENERATE[x86_64-gf2m.s]=asm/x86_64-gf2m.pl
GENERATE[rsaz-x86_64.s]=asm/rsaz-x86_64.pl
GENERATE[rsaz-avx2.s]=asm/rsaz-avx2.pl
GENERATE[rsaz-avx512.s]=asm/rsaz-avx512.pl
GENERATE[bn-ia64.s]=asm/ia64.S
GENERATE[ia64-mont.s]=asm/ia64-mont.pl
GENERATE[parisc-mont.s]=asm/parisc-mont.pl
# ppc - AIX, Linux, MacOS X...
GENERATE[bn-ppc.s]=asm/ppc.pl
GENERATE[ppc-mont.s]=asm/ppc-mont.pl
GENERATE[ppc64-mont.s]=asm/ppc64-mont.pl
GENERATE[alpha-mont.S]=asm/alpha-mont.pl
GENERATE[armv4-mont.S]=asm/armv4-mont.pl
INCLUDE[armv4-mont.o]=..
GENERATE[armv4-gf2m.S]=asm/armv4-gf2m.pl
INCLUDE[armv4-gf2m.o]=..
GENERATE[armv8-mont.S]=asm/armv8-mont.pl
INCLUDE[armv8-mont.o]=..
diff --git a/crypto/bn/rsa_sup_mul.c b/crypto/bn/rsa_sup_mul.c
deleted file mode 100644
index 0e0d02e1946e..000000000000
--- a/crypto/bn/rsa_sup_mul.c
+++ /dev/null
@@ -1,604 +0,0 @@
-#include <openssl/e_os2.h>
-#include <stddef.h>
-#include <sys/types.h>
-#include <string.h>
-#include <openssl/bn.h>
-#include <openssl/err.h>
-#include <openssl/rsaerr.h>
-#include "internal/endian.h"
-#include "internal/numbers.h"
-#include "internal/constant_time.h"
-#include "bn_local.h"
-
-# if BN_BYTES == 8
-typedef uint64_t limb_t;
-# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16
-typedef uint128_t limb2_t;
-# define HAVE_LIMB2_T
-# endif
-# define LIMB_BIT_SIZE 64
-# define LIMB_BYTE_SIZE 8
-# elif BN_BYTES == 4
-typedef uint32_t limb_t;
-typedef uint64_t limb2_t;
-# define LIMB_BIT_SIZE 32
-# define LIMB_BYTE_SIZE 4
-# define HAVE_LIMB2_T
-# else
-# error "Not supported"
-# endif
-
-/*
- * For multiplication we're using schoolbook multiplication,
- * so if we have two numbers, each with 6 "digits" (words)
- * the multiplication is calculated as follows:
- * A B C D E F
- * x I J K L M N
- * --------------
- * N*F
- * N*E
- * N*D
- * N*C
- * N*B
- * N*A
- * M*F
- * M*E
- * M*D
- * M*C
- * M*B
- * M*A
- * L*F
- * L*E
- * L*D
- * L*C
- * L*B
- * L*A
- * K*F
- * K*E
- * K*D
- * K*C
- * K*B
- * K*A
- * J*F
- * J*E
- * J*D
- * J*C
- * J*B
- * J*A
- * I*F
- * I*E
- * I*D
- * I*C
- * I*B
- * + I*A
- * ==========================
- * N*B N*D N*F
- * + N*A N*C N*E
- * + M*B M*D M*F
- * + M*A M*C M*E
- * + L*B L*D L*F
- * + L*A L*C L*E
- * + K*B K*D K*F
- * + K*A K*C K*E
- * + J*B J*D J*F
- * + J*A J*C J*E
- * + I*B I*D I*F
- * + I*A I*C I*E
- *
- * 1+1 1+3 1+5
- * 1+0 1+2 1+4
- * 0+1 0+3 0+5
- * 0+0 0+2 0+4
- *
- * 0 1 2 3 4 5 6
- * which requires n^2 multiplications and 2n full length additions
- * as we can keep every other result of limb multiplication in two separate
- * limbs
- */
-
-#if defined HAVE_LIMB2_T
-static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b)
-{
- limb2_t t;
- /*
- * this is idiomatic code to tell compiler to use the native mul
- * those three lines will actually compile to single instruction
- */
-
- t = (limb2_t)a * b;
- *hi = t >> LIMB_BIT_SIZE;
- *lo = (limb_t)t;
-}
-#elif (BN_BYTES == 8) && (defined _MSC_VER)
-/* https://learn.microsoft.com/en-us/cpp/intrinsics/umul128?view=msvc-170 */
-#pragma intrinsic(_umul128)
-static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b)
-{
- *lo = _umul128(a, b, hi);
-}
-#else
-/*
- * if the compiler doesn't have either a 128bit data type nor a "return
- * high 64 bits of multiplication"
- */
-static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b)
-{
- limb_t a_low = (limb_t)(uint32_t)a;
- limb_t a_hi = a >> 32;
- limb_t b_low = (limb_t)(uint32_t)b;
- limb_t b_hi = b >> 32;
-
- limb_t p0 = a_low * b_low;
- limb_t p1 = a_low * b_hi;
- limb_t p2 = a_hi * b_low;
- limb_t p3 = a_hi * b_hi;
-
- uint32_t cy = (uint32_t)(((p0 >> 32) + (uint32_t)p1 + (uint32_t)p2) >> 32);
-
- *lo = p0 + (p1 << 32) + (p2 << 32);
- *hi = p3 + (p1 >> 32) + (p2 >> 32) + cy;
-}
-#endif
-
-/* add two limbs with carry in, return carry out */
-static ossl_inline limb_t _add_limb(limb_t *ret, limb_t a, limb_t b, limb_t carry)
-{
- limb_t carry1, carry2, t;
- /*
- * `c = a + b; if (c < a)` is idiomatic code that makes compilers
- * use add with carry on assembly level
- */
-
- *ret = a + carry;
- if (*ret < a)
- carry1 = 1;
- else
- carry1 = 0;
-
- t = *ret;
- *ret = t + b;
- if (*ret < t)
- carry2 = 1;
- else
- carry2 = 0;
-
- return carry1 + carry2;
-}
-
-/*
- * add two numbers of the same size, return overflow
- *
- * add a to b, place result in ret; all arrays need to be n limbs long
- * return overflow from addition (0 or 1)
- */
-static ossl_inline limb_t add(limb_t *ret, limb_t *a, limb_t *b, size_t n)
-{
- limb_t c = 0;
- ossl_ssize_t i;
-
- for(i = n - 1; i > -1; i--)
- c = _add_limb(&ret[i], a[i], b[i], c);
-
- return c;
-}
-
-/*
- * return number of limbs necessary for temporary values
- * when multiplying numbers n limbs large
- */
-static ossl_inline size_t mul_limb_numb(size_t n)
-{
- return 2 * n * 2;
-}
-
-/*
- * multiply two numbers of the same size
- *
- * multiply a by b, place result in ret; a and b need to be n limbs long
- * ret needs to be 2*n limbs long, tmp needs to be mul_limb_numb(n) limbs
- * long
- */
-static void limb_mul(limb_t *ret, limb_t *a, limb_t *b, size_t n, limb_t *tmp)
-{
- limb_t *r_odd, *r_even;
- size_t i, j, k;
-
- r_odd = tmp;
- r_even = &tmp[2 * n];
-
- memset(ret, 0, 2 * n * sizeof(limb_t));
-
- for (i = 0; i < n; i++) {
- for (k = 0; k < i + n + 1; k++) {
- r_even[k] = 0;
- r_odd[k] = 0;
- }
- for (j = 0; j < n; j++) {
- /*
- * place results from even and odd limbs in separate arrays so that
- * we don't have to calculate overflow every time we get individual
- * limb multiplication result
- */
- if (j % 2 == 0)
- _mul_limb(&r_even[i + j], &r_even[i + j + 1], a[i], b[j]);
- else
- _mul_limb(&r_odd[i + j], &r_odd[i + j + 1], a[i], b[j]);
- }
- /*
- * skip the least significant limbs when adding multiples of
- * more significant limbs (they're zero anyway)
- */
- add(ret, ret, r_even, n + i + 1);
- add(ret, ret, r_odd, n + i + 1);
- }
-}
-
-/* modifies the value in place by performing a right shift by one bit */
-static ossl_inline void rshift1(limb_t *val, size_t n)
-{
- limb_t shift_in = 0, shift_out = 0;
- size_t i;
-
- for (i = 0; i < n; i++) {
- shift_out = val[i] & 1;
- val[i] = shift_in << (LIMB_BIT_SIZE - 1) | (val[i] >> 1);
- shift_in = shift_out;
- }
-}
-
-/* extend the LSB of flag to all bits of limb */
-static ossl_inline limb_t mk_mask(limb_t flag)
-{
- flag |= flag << 1;
- flag |= flag << 2;
- flag |= flag << 4;
- flag |= flag << 8;
- flag |= flag << 16;
-#if (LIMB_BYTE_SIZE == 8)
- flag |= flag << 32;
-#endif
- return flag;
-}
-
-/*
- * copy from either a or b to ret based on flag
- * when flag == 0, then copies from b
- * when flag == 1, then copies from a
- */
-static ossl_inline void cselect(limb_t flag, limb_t *ret, limb_t *a, limb_t *b, size_t n)
-{
- /*
- * would be more efficient with non volatile mask, but then gcc
- * generates code with jumps
- */
- volatile limb_t mask;
- size_t i;
-
- mask = mk_mask(flag);
- for (i = 0; i < n; i++) {
-#if (LIMB_BYTE_SIZE == 8)
- ret[i] = constant_time_select_64(mask, a[i], b[i]);
-#else
- ret[i] = constant_time_select_32(mask, a[i], b[i]);
-#endif
- }
-}
-
-static limb_t _sub_limb(limb_t *ret, limb_t a, limb_t b, limb_t borrow)
-{
- limb_t borrow1, borrow2, t;
- /*
- * while it doesn't look constant-time, this is idiomatic code
- * to tell compilers to use the carry bit from subtraction
- */
-
- *ret = a - borrow;
- if (*ret > a)
- borrow1 = 1;
- else
- borrow1 = 0;
-
- t = *ret;
- *ret = t - b;
- if (*ret > t)
- borrow2 = 1;
- else
- borrow2 = 0;
-
- return borrow1 + borrow2;
-}
-
-/*
- * place the result of a - b into ret, return the borrow bit.
- * All arrays need to be n limbs long
- */
-static limb_t sub(limb_t *ret, limb_t *a, limb_t *b, size_t n)
-{
- limb_t borrow = 0;
- ossl_ssize_t i;
-
- for (i = n - 1; i > -1; i--)
- borrow = _sub_limb(&ret[i], a[i], b[i], borrow);
-
- return borrow;
-}
-
-/* return the number of limbs necessary to allocate for the mod() tmp operand */
-static ossl_inline size_t mod_limb_numb(size_t anum, size_t modnum)
-{
- return (anum + modnum) * 3;
-}
-
-/*
- * calculate a % mod, place the result in ret
- * size of a is defined by anum, size of ret and mod is modnum,
- * size of tmp is returned by mod_limb_numb()
- */
-static void mod(limb_t *ret, limb_t *a, size_t anum, limb_t *mod,
- size_t modnum, limb_t *tmp)
-{
- limb_t *atmp, *modtmp, *rettmp;
- limb_t res;
- size_t i;
-
- memset(tmp, 0, mod_limb_numb(anum, modnum) * LIMB_BYTE_SIZE);
-
- atmp = tmp;
- modtmp = &tmp[anum + modnum];
- rettmp = &tmp[(anum + modnum) * 2];
-
- for (i = modnum; i <modnum + anum; i++)
- atmp[i] = a[i-modnum];
-
- for (i = 0; i < modnum; i++)
- modtmp[i] = mod[i];
-
- for (i = 0; i < anum * LIMB_BIT_SIZE; i++) {
- rshift1(modtmp, anum + modnum);
- res = sub(rettmp, atmp, modtmp, anum+modnum);
- cselect(res, atmp, atmp, rettmp, anum+modnum);
- }
-
- memcpy(ret, &atmp[anum], sizeof(limb_t) * modnum);
-}
-
-/* necessary size of tmp for a _mul_add_limb() call with provided anum */
-static ossl_inline size_t _mul_add_limb_numb(size_t anum)
-{
- return 2 * (anum + 1);
-}
-
-/* multiply a by m, add to ret, return carry */
-static limb_t _mul_add_limb(limb_t *ret, limb_t *a, size_t anum,
- limb_t m, limb_t *tmp)
-{
- limb_t carry = 0;
- limb_t *r_odd, *r_even;
- size_t i;
-
- memset(tmp, 0, sizeof(limb_t) * (anum + 1) * 2);
-
- r_odd = tmp;
- r_even = &tmp[anum + 1];
-
- for (i = 0; i < anum; i++) {
- /*
- * place the results from even and odd limbs in separate arrays
- * so that we have to worry about carry just once
- */
- if (i % 2 == 0)
- _mul_limb(&r_even[i], &r_even[i + 1], a[i], m);
- else
- _mul_limb(&r_odd[i], &r_odd[i + 1], a[i], m);
- }
- /* assert: add() carry here will be equal zero */
- add(r_even, r_even, r_odd, anum + 1);
- /*
- * while here it will not overflow as the max value from multiplication
- * is -2 while max overflow from addition is 1, so the max value of
- * carry is -1 (i.e. max int)
- */
- carry = add(ret, ret, &r_even[1], anum) + r_even[0];
-
- return carry;
-}
-
-static ossl_inline size_t mod_montgomery_limb_numb(size_t modnum)
-{
- return modnum * 2 + _mul_add_limb_numb(modnum);
-}
-
-/*
- * calculate a % mod, place result in ret
- * assumes that a is in Montgomery form with the R (Montgomery modulus) being
- * smallest power of two big enough to fit mod and that's also a power
- * of the count of number of bits in limb_t (B).
- * For calculation, we also need n', such that mod * n' == -1 mod B.
- * anum must be <= 2 * modnum
- * ret needs to be modnum words long
- * tmp needs to be mod_montgomery_limb_numb(modnum) limbs long
- */
-static void mod_montgomery(limb_t *ret, limb_t *a, size_t anum, limb_t *mod,
- size_t modnum, limb_t ni0, limb_t *tmp)
-{
- limb_t carry, v;
- limb_t *res, *rp, *tmp2;
- ossl_ssize_t i;
-
- res = tmp;
- /*
- * for intermediate result we need an integer twice as long as modulus
- * but keep the input in the least significant limbs
- */
- memset(res, 0, sizeof(limb_t) * (modnum * 2));
- memcpy(&res[modnum * 2 - anum], a, sizeof(limb_t) * anum);
- rp = &res[modnum];
- tmp2 = &res[modnum * 2];
-
- carry = 0;
-
- /* add multiples of the modulus to the value until R divides it cleanly */
- for (i = modnum; i > 0; i--, rp--) {
- v = _mul_add_limb(rp, mod, modnum, rp[modnum-1] * ni0, tmp2);
- v = v + carry + rp[-1];
- carry |= (v != rp[-1]);
- carry &= (v <= rp[-1]);
- rp[-1] = v;
- }
-
- /* perform the final reduction by mod... */
- carry -= sub(ret, rp, mod, modnum);
-
- /* ...conditionally */
- cselect(carry, ret, rp, ret, modnum);
-}
-
-/* allocated buffer should be freed afterwards */
-static void BN_to_limb(const BIGNUM *bn, limb_t *buf, size_t limbs)
-{
- int i;
- int real_limbs = (BN_num_bytes(bn) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE;
- limb_t *ptr = buf + (limbs - real_limbs);
-
- for (i = 0; i < real_limbs; i++)
- ptr[i] = bn->d[real_limbs - i - 1];
-}
-
-#if LIMB_BYTE_SIZE == 8
-static ossl_inline uint64_t be64(uint64_t host)
-{
- uint64_t big = 0;
- DECLARE_IS_ENDIAN;
-
- if (!IS_LITTLE_ENDIAN)
- return host;
-
- big |= (host & 0xff00000000000000) >> 56;
- big |= (host & 0x00ff000000000000) >> 40;
- big |= (host & 0x0000ff0000000000) >> 24;
- big |= (host & 0x000000ff00000000) >> 8;
- big |= (host & 0x00000000ff000000) << 8;
- big |= (host & 0x0000000000ff0000) << 24;
- big |= (host & 0x000000000000ff00) << 40;
- big |= (host & 0x00000000000000ff) << 56;
- return big;
-}
-
-#else
-/* Not all platforms have htobe32(). */
-static ossl_inline uint32_t be32(uint32_t host)
-{
- uint32_t big = 0;
- DECLARE_IS_ENDIAN;
-
- if (!IS_LITTLE_ENDIAN)
- return host;
-
- big |= (host & 0xff000000) >> 24;
- big |= (host & 0x00ff0000) >> 8;
- big |= (host & 0x0000ff00) << 8;
- big |= (host & 0x000000ff) << 24;
- return big;
-}
-#endif
-
-/*
- * We assume that intermediate, possible_arg2, blinding, and ctx are used
- * similar to BN_BLINDING_invert_ex() arguments.
- * to_mod is RSA modulus.
- * buf and num is the serialization buffer and its length.
- *
- * Here we use classic/Montgomery multiplication and modulo. After the calculation finished
- * we serialize the new structure instead of BIGNUMs taking endianness into account.
- */
-int ossl_bn_rsa_do_unblind(const BIGNUM *intermediate,
- const BN_BLINDING *blinding,
- const BIGNUM *possible_arg2,
- const BIGNUM *to_mod, BN_CTX *ctx,
- unsigned char *buf, int num)
-{
- limb_t *l_im = NULL, *l_mul = NULL, *l_mod = NULL;
- limb_t *l_ret = NULL, *l_tmp = NULL, l_buf;
- size_t l_im_count = 0, l_mul_count = 0, l_size = 0, l_mod_count = 0;
- size_t l_tmp_count = 0;
- int ret = 0;
- size_t i;
- unsigned char *tmp;
- const BIGNUM *arg1 = intermediate;
- const BIGNUM *arg2 = (possible_arg2 == NULL) ? blinding->Ai : possible_arg2;
-
- l_im_count = (BN_num_bytes(arg1) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE;
- l_mul_count = (BN_num_bytes(arg2) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE;
- l_mod_count = (BN_num_bytes(to_mod) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE;
-
- l_size = l_im_count > l_mul_count ? l_im_count : l_mul_count;
- l_im = OPENSSL_zalloc(l_size * LIMB_BYTE_SIZE);
- l_mul = OPENSSL_zalloc(l_size * LIMB_BYTE_SIZE);
- l_mod = OPENSSL_zalloc(l_mod_count * LIMB_BYTE_SIZE);
-
- if ((l_im == NULL) || (l_mul == NULL) || (l_mod == NULL))
- goto err;
-
- BN_to_limb(arg1, l_im, l_size);
- BN_to_limb(arg2, l_mul, l_size);
- BN_to_limb(to_mod, l_mod, l_mod_count);
-
- l_ret = OPENSSL_malloc(2 * l_size * LIMB_BYTE_SIZE);
-
- if (blinding->m_ctx != NULL) {
- l_tmp_count = mul_limb_numb(l_size) > mod_montgomery_limb_numb(l_mod_count) ?
- mul_limb_numb(l_size) : mod_montgomery_limb_numb(l_mod_count);
- l_tmp = OPENSSL_malloc(l_tmp_count * LIMB_BYTE_SIZE);
- } else {
- l_tmp_count = mul_limb_numb(l_size) > mod_limb_numb(2 * l_size, l_mod_count) ?
- mul_limb_numb(l_size) : mod_limb_numb(2 * l_size, l_mod_count);
- l_tmp = OPENSSL_malloc(l_tmp_count * LIMB_BYTE_SIZE);
- }
-
- if ((l_ret == NULL) || (l_tmp == NULL))
- goto err;
-
- if (blinding->m_ctx != NULL) {
- limb_mul(l_ret, l_im, l_mul, l_size, l_tmp);
- mod_montgomery(l_ret, l_ret, 2 * l_size, l_mod, l_mod_count,
- blinding->m_ctx->n0[0], l_tmp);
- } else {
- limb_mul(l_ret, l_im, l_mul, l_size, l_tmp);
- mod(l_ret, l_ret, 2 * l_size, l_mod, l_mod_count, l_tmp);
- }
-
- /* modulus size in bytes can be equal to num but after limbs conversion it becomes bigger */
- if (num < BN_num_bytes(to_mod)) {
- ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT);
- goto err;
- }
-
- memset(buf, 0, num);
- tmp = buf + num - BN_num_bytes(to_mod);
- for (i = 0; i < l_mod_count; i++) {
-#if LIMB_BYTE_SIZE == 8
- l_buf = be64(l_ret[i]);
-#else
- l_buf = be32(l_ret[i]);
-#endif
- if (i == 0) {
- int delta = LIMB_BYTE_SIZE - ((l_mod_count * LIMB_BYTE_SIZE) - num);
-
- memcpy(tmp, ((char *)&l_buf) + LIMB_BYTE_SIZE - delta, delta);
- tmp += delta;
- } else {
- memcpy(tmp, &l_buf, LIMB_BYTE_SIZE);
- tmp += LIMB_BYTE_SIZE;
- }
- }
- ret = num;
-
- err:
- OPENSSL_free(l_im);
- OPENSSL_free(l_mul);
- OPENSSL_free(l_mod);
- OPENSSL_free(l_tmp);
- OPENSSL_free(l_ret);
-
- return ret;
-}
diff --git a/crypto/build.info b/crypto/build.info
index 16584234feb7..b90390ae864c 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -1,140 +1,138 @@
# Note that these directories are filtered in Configure. Look for %skipdir
# there for further explanations.
SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 conf \
txt_db pkcs7 pkcs12 ui kdf store property \
md2 md4 md5 sha mdc2 hmac ripemd whrlpool poly1305 \
siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \
seed sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \
err comp http ocsp cms ts srp cmac ct async ess crmf cmp encode_decode \
ffc
LIBS=../libcrypto
$UPLINKSRC=
$UPLINKDEF=
IF[{- !$disabled{uplink} -}]
$UPLINKSRC_common=../ms/uplink.c
$UPLINKSRC_x86=$UPLINKSRC_common uplink-x86.S
$UPLINKSRC_x86_64=$UPLINKSRC_common uplink-x86_64.s
$UPLINKSRC_ia64=$UPLINKSRC_common uplink-ia64.s
IF[$UPLINKSRC_{- $target{uplink_arch} -}]
$UPLINKSRC=$UPLINKSRC_{- $target{uplink_arch} -}
$UPLINKDEF=OPENSSL_USE_APPLINK
ENDIF
ENDIF
$CPUIDASM=mem_clr.c
$CPUIDDEF=
IF[{- !$disabled{asm} && $config{processor} ne '386' -}]
$CPUIDASM_x86=x86cpuid.S
$CPUIDASM_x86_64=x86_64cpuid.s
$CPUIDASM_ia64=ia64cpuid.s
$CPUIDASM_sparcv9=sparcv9cap.c sparccpuid.S
$CPUIDASM_alpha=alphacpuid.s
$CPUIDASM_s390x=s390xcap.c s390xcpuid.S
$CPUIDASM_armv4=armcap.c armv4cpuid.S
$CPUIDASM_aarch64=armcap.c arm64cpuid.S
$CPUIDASM_parisc11=pariscid.s
$CPUIDASM_parisc20_64=$CPUIDASM_parisc11
$CPUIDASM_ppc32=ppccpuid.s ppccap.c
$CPUIDASM_ppc64=$CPUIDASM_ppc32
$CPUIDASM_c64xplus=c64xpluscpuid.s
# Now that we have defined all the arch specific variables, use the
# appropriate one, and define the appropriate macros
IF[$CPUIDASM_{- $target{asm_arch} -}]
$CPUIDASM=$CPUIDASM_{- $target{asm_arch} -}
$CPUIDDEF=OPENSSL_CPUID_OBJ
ENDIF
ENDIF
# CPUID support. We need to add that explicitly in every shared library and
# provider module that uses it. ctype.c is included here because the CPUID
# uses functions from there to parse magic environment variables.
$CPUID_COMMON=$CPUIDASM cpuid.c ctype.c
INCLUDE[cpuid.o]=..
SOURCE[../libcrypto]=$CPUID_COMMON
DEFINE[../libcrypto]=$CPUIDDEF
SOURCE[../providers/libfips.a]=$CPUID_COMMON
DEFINE[../providers/libfips.a]=$CPUIDDEF
# We only need to include the CPUID stuff in the legacy provider when it's a
# separate module and it's dynamically linked with libcrypto. Otherwise, it
# already gets everything that the static libcrypto.a has, and doesn't need it
# added again.
IF[{- !$disabled{module} && !$disabled{shared} -}]
SOURCE[../providers/liblegacy.a]=$CPUID_COMMON
DEFINE[../providers/liblegacy.a]=$CPUIDDEF
ENDIF
# Implementations are now spread across several libraries, so the CPUID define
# need to be applied to all affected libraries and modules.
DEFINE[../providers/libcommon.a]=$CPUIDDEF
DEFINE[../providers/libdefault.a]=$CPUIDDEF
# The Core
$CORE_COMMON=provider_core.c provider_predefined.c \
core_fetch.c core_algorithm.c core_namemap.c self_test_core.c
SOURCE[../libcrypto]=$CORE_COMMON provider_conf.c
SOURCE[../providers/libfips.a]=$CORE_COMMON
# Central utilities
$UTIL_COMMON=\
cryptlib.c params.c params_from_text.c bsearch.c ex_data.c o_str.c \
threads_pthread.c threads_win.c threads_none.c initthread.c \
context.c sparse_array.c asn1_dsa.c packet.c param_build.c \
param_build_set.c der_writer.c threads_lib.c params_dup.c
-IF[{- !$disabled{shared} -}]
- SOURCE[../libssl]=sparse_array.c
-ENDIF
+SHARED_SOURCE[../libssl]=sparse_array.c
SOURCE[../libcrypto]=$UTIL_COMMON \
mem.c mem_sec.c \
cversion.c info.c cpt_err.c ebcdic.c uid.c o_time.c o_dir.c \
o_fopen.c getenv.c o_init.c init.c trace.c provider.c provider_child.c \
punycode.c passphrase.c
SOURCE[../providers/libfips.a]=$UTIL_COMMON
SOURCE[../libcrypto]=$UPLINKSRC
DEFINE[../libcrypto]=$UPLINKDEF
DEPEND[info.o]=buildinf.h
DEPEND[cversion.o]=buildinf.h
GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(CC) $(LIB_CFLAGS) $(CPPFLAGS_Q)" "$(PLATFORM)"
GENERATE[uplink-x86.S]=../ms/uplink-x86.pl
GENERATE[uplink-x86_64.s]=../ms/uplink-x86_64.pl
GENERATE[uplink-ia64.s]=../ms/uplink-ia64.pl
GENERATE[x86cpuid.S]=x86cpuid.pl
DEPEND[x86cpuid.s]=perlasm/x86asm.pl
GENERATE[x86_64cpuid.s]=x86_64cpuid.pl
GENERATE[ia64cpuid.s]=ia64cpuid.S
GENERATE[ppccpuid.s]=ppccpuid.pl
GENERATE[pariscid.s]=pariscid.pl
GENERATE[alphacpuid.s]=alphacpuid.pl
GENERATE[arm64cpuid.S]=arm64cpuid.pl
INCLUDE[arm64cpuid.o]=.
GENERATE[armv4cpuid.S]=armv4cpuid.pl
INCLUDE[armv4cpuid.o]=.
GENERATE[s390xcpuid.S]=s390xcpuid.pl
INCLUDE[s390xcpuid.o]=.
IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}]
SHARED_SOURCE[../libcrypto]=dllmain.c
ENDIF
diff --git a/crypto/cmp/cmp_client.c b/crypto/cmp/cmp_client.c
index 22ae7d07e82d..dc41f4c3b7d9 100644
--- a/crypto/cmp/cmp_client.c
+++ b/crypto/cmp/cmp_client.c
@@ -1,890 +1,918 @@
/*
* 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,
- -1 /* any rid */);
+ 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);
if (!sk_ASN1_UTF8STRING_push(ctx->statusString, ASN1_STRING_dup(str)))
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 fail_info,
- const char *txt)
+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 */
- if ((certConf = ossl_cmp_certConf_new(ctx, fail_info, txt)) == NULL)
+ 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;
- EVP_PKEY *privkey;
if (!ossl_assert(ctx != NULL && crep != NULL))
return NULL;
- privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
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(crep, ctx, privkey);
+ 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;
- ossl_cmp_debug(ctx, "trying to build chain for newly enrolled cert");
- chain = X509_build_chain(cert, ctx->untrusted, out_trusted /* maybe NULL */,
- 0, ctx->libctx, ctx->propq);
+ 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 building chain for newly enrolled cert");
+ ossl_cmp_err(ctx, "failed to validate newly enrolled cert");
fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData;
} else {
ossl_cmp_debug(ctx,
- "succeeded building proper chain for newly enrolled cert");
+ "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_newPkey(ctx /* may be NULL */, 0);
+ 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 == -1) {
- /* for OSSL_CMP_PKIBODY_P10CR learn CertReqId from response */
+ if (rid == OSSL_CMP_CERTREQID_NONE) { /* used for OSSL_CMP_PKIBODY_P10CR */
rid = ossl_cmp_asn1_get_int(crep->certReqId);
- if (rid == -1) {
+ 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, fail_info, txt))
+ 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 ? -1 : OSSL_CMP_CERTREQID;
+ 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 ? -1 : OSSL_CMP_CERTREQID;
+ 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/cmp/cmp_ctx.c b/crypto/cmp/cmp_ctx.c
index 4b610b746e45..9d9bd357daf7 100644
--- a/crypto/cmp/cmp_ctx.c
+++ b/crypto/cmp/cmp_ctx.c
@@ -1,1157 +1,1173 @@
/*
- * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <openssl/trace.h>
#include <openssl/bio.h>
#include <openssl/ocsp.h> /* for OCSP_REVOKED_STATUS_* */
#include "cmp_local.h"
/* explicit #includes not strictly needed since implied by the above: */
#include <openssl/cmp.h>
#include <openssl/crmf.h>
#include <openssl/err.h>
/*
* Get current certificate store containing trusted root CA certs
*/
X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return ctx->trusted;
}
/*
* Set certificate store containing trusted (root) CA certs and possibly CRLs
* and a cert verification callback function used for CMP server authentication.
* Any already existing store entry is freed. Given NULL, the entry is reset.
*/
int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
X509_STORE_free(ctx->trusted);
ctx->trusted = store;
return 1;
}
/* Get current list of non-trusted intermediate certs */
STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return ctx->untrusted;
}
/*
* Set untrusted certificates for path construction in authentication of
* the CMP server and potentially others (TLS server, newly enrolled cert).
*/
int OSSL_CMP_CTX_set1_untrusted(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs)
{
STACK_OF(X509) *untrusted = NULL;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (!ossl_x509_add_certs_new(&untrusted, certs,
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
goto err;
sk_X509_pop_free(ctx->untrusted, X509_free);
ctx->untrusted = untrusted;
return 1;
err:
sk_X509_pop_free(untrusted, X509_free);
return 0;
}
static int cmp_ctx_set_md(OSSL_CMP_CTX *ctx, EVP_MD **pmd, int nid)
{
EVP_MD *md = EVP_MD_fetch(ctx->libctx, OBJ_nid2sn(nid), ctx->propq);
/* fetching in advance to be able to throw error early if unsupported */
if (md == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
EVP_MD_free(*pmd);
*pmd = md;
return 1;
}
/*
* Allocates and initializes OSSL_CMP_CTX context structure with default values.
* Returns new context on success, NULL on error
*/
OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq)
{
OSSL_CMP_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL)
goto err;
ctx->libctx = libctx;
if (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL)
goto oom;
ctx->log_verbosity = OSSL_CMP_LOG_INFO;
ctx->status = OSSL_CMP_PKISTATUS_unspecified;
ctx->failInfoCode = -1;
ctx->keep_alive = 1;
ctx->msg_timeout = -1;
if ((ctx->untrusted = sk_X509_new_null()) == NULL)
goto oom;
ctx->pbm_slen = 16;
if (!cmp_ctx_set_md(ctx, &ctx->pbm_owf, NID_sha256))
goto err;
ctx->pbm_itercnt = 500;
ctx->pbm_mac = NID_hmac_sha1;
if (!cmp_ctx_set_md(ctx, &ctx->digest, NID_sha256))
goto err;
ctx->popoMethod = OSSL_CRMF_POPO_SIGNATURE;
ctx->revocationReason = CRL_REASON_NONE;
/* all other elements are initialized to 0 or NULL, respectively */
return ctx;
oom:
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
err:
OSSL_CMP_CTX_free(ctx);
return NULL;
}
#define OSSL_CMP_ITAVs_free(itavs) \
sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
#define X509_EXTENSIONS_free(exts) \
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free)
#define OSSL_CMP_PKIFREETEXT_free(text) \
sk_ASN1_UTF8STRING_pop_free(text, ASN1_UTF8STRING_free)
/* Prepare the OSSL_CMP_CTX for next use, partly re-initializing OSSL_CMP_CTX */
int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (ctx->http_ctx != NULL) {
(void)OSSL_HTTP_close(ctx->http_ctx, 1);
ossl_cmp_debug(ctx, "disconnected from CMP server");
ctx->http_ctx = NULL;
}
ctx->status = OSSL_CMP_PKISTATUS_unspecified;
ctx->failInfoCode = -1;
OSSL_CMP_ITAVs_free(ctx->genm_ITAVs);
ctx->genm_ITAVs = NULL;
return ossl_cmp_ctx_set0_statusString(ctx, NULL)
&& ossl_cmp_ctx_set0_newCert(ctx, NULL)
&& ossl_cmp_ctx_set1_newChain(ctx, NULL)
&& ossl_cmp_ctx_set1_caPubs(ctx, NULL)
&& ossl_cmp_ctx_set1_extraCertsIn(ctx, NULL)
&& ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL)
&& OSSL_CMP_CTX_set1_transactionID(ctx, NULL)
&& OSSL_CMP_CTX_set1_senderNonce(ctx, NULL)
&& ossl_cmp_ctx_set1_recipNonce(ctx, NULL);
}
/* Frees OSSL_CMP_CTX variables allocated in OSSL_CMP_CTX_new() */
void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx)
{
if (ctx == NULL)
return;
if (ctx->http_ctx != NULL) {
(void)OSSL_HTTP_close(ctx->http_ctx, 1);
ossl_cmp_debug(ctx, "disconnected from CMP server");
}
OPENSSL_free(ctx->propq);
OPENSSL_free(ctx->serverPath);
OPENSSL_free(ctx->server);
OPENSSL_free(ctx->proxy);
OPENSSL_free(ctx->no_proxy);
X509_free(ctx->srvCert);
X509_free(ctx->validatedSrvCert);
X509_NAME_free(ctx->expected_sender);
X509_STORE_free(ctx->trusted);
sk_X509_pop_free(ctx->untrusted, X509_free);
X509_free(ctx->cert);
sk_X509_pop_free(ctx->chain, X509_free);
EVP_PKEY_free(ctx->pkey);
ASN1_OCTET_STRING_free(ctx->referenceValue);
if (ctx->secretValue != NULL)
OPENSSL_cleanse(ctx->secretValue->data, ctx->secretValue->length);
ASN1_OCTET_STRING_free(ctx->secretValue);
EVP_MD_free(ctx->pbm_owf);
X509_NAME_free(ctx->recipient);
EVP_MD_free(ctx->digest);
ASN1_OCTET_STRING_free(ctx->transactionID);
ASN1_OCTET_STRING_free(ctx->senderNonce);
ASN1_OCTET_STRING_free(ctx->recipNonce);
sk_OSSL_CMP_ITAV_pop_free(ctx->geninfo_ITAVs, OSSL_CMP_ITAV_free);
sk_X509_pop_free(ctx->extraCertsOut, X509_free);
EVP_PKEY_free(ctx->newPkey);
X509_NAME_free(ctx->issuer);
X509_NAME_free(ctx->subjectName);
sk_GENERAL_NAME_pop_free(ctx->subjectAltNames, GENERAL_NAME_free);
sk_X509_EXTENSION_pop_free(ctx->reqExtensions, X509_EXTENSION_free);
sk_POLICYINFO_pop_free(ctx->policies, POLICYINFO_free);
X509_free(ctx->oldCert);
X509_REQ_free(ctx->p10CSR);
sk_OSSL_CMP_ITAV_pop_free(ctx->genm_ITAVs, OSSL_CMP_ITAV_free);
sk_ASN1_UTF8STRING_pop_free(ctx->statusString, ASN1_UTF8STRING_free);
X509_free(ctx->newCert);
sk_X509_pop_free(ctx->newChain, X509_free);
sk_X509_pop_free(ctx->caPubs, X509_free);
sk_X509_pop_free(ctx->extraCertsIn, X509_free);
OPENSSL_free(ctx);
}
int ossl_cmp_ctx_set_status(OSSL_CMP_CTX *ctx, int status)
{
if (!ossl_assert(ctx != NULL))
return 0;
ctx->status = status;
return 1;
}
/*
* Returns the PKIStatus from the last CertRepMessage
* or Revocation Response or error message, -1 on error
*/
int OSSL_CMP_CTX_get_status(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return -1;
}
return ctx->status;
}
/*
* Returns the statusString from the last CertRepMessage
* or Revocation Response or error message, NULL on error
*/
OSSL_CMP_PKIFREETEXT *OSSL_CMP_CTX_get0_statusString(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return ctx->statusString;
}
int ossl_cmp_ctx_set0_statusString(OSSL_CMP_CTX *ctx,
OSSL_CMP_PKIFREETEXT *text)
{
if (!ossl_assert(ctx != NULL))
return 0;
sk_ASN1_UTF8STRING_pop_free(ctx->statusString, ASN1_UTF8STRING_free);
ctx->statusString = text;
return 1;
}
int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert)
{
if (!ossl_assert(ctx != NULL))
return 0;
X509_free(ctx->validatedSrvCert);
ctx->validatedSrvCert = cert;
return 1;
}
/* Set callback function for checking if the cert is ok or should be rejected */
int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx->certConf_cb = cb;
return 1;
}
/*
* Set argument, respectively a pointer to a structure containing arguments,
* optionally to be used by the certConf callback.
*/
int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx->certConf_cb_arg = arg;
return 1;
}
/*
* Get argument, respectively the pointer to a structure containing arguments,
* optionally to be used by certConf callback.
* Returns callback argument set previously (NULL if not set or on error)
*/
void *OSSL_CMP_CTX_get_certConf_cb_arg(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return ctx->certConf_cb_arg;
}
#ifndef OPENSSL_NO_TRACE
static size_t ossl_cmp_log_trace_cb(const char *buf, size_t cnt,
int category, int cmd, void *vdata)
{
OSSL_CMP_CTX *ctx = vdata;
const char *msg;
OSSL_CMP_severity level = -1;
char *func = NULL;
char *file = NULL;
int line = 0;
if (buf == NULL || cnt == 0 || cmd != OSSL_TRACE_CTRL_WRITE || ctx == NULL)
return 0;
if (ctx->log_cb == NULL)
return 1; /* silently drop message */
msg = ossl_cmp_log_parse_metadata(buf, &level, &func, &file, &line);
if (level > ctx->log_verbosity) /* excludes the case level is unknown */
goto end; /* suppress output since severity is not sufficient */
if (!ctx->log_cb(func != NULL ? func : "(no func)",
file != NULL ? file : "(no file)",
line, level, msg))
cnt = 0;
end:
OPENSSL_free(func);
OPENSSL_free(file);
return cnt;
}
#endif
/* Print CMP log messages (i.e., diagnostic info) via the log cb of the ctx */
int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx,
const char *func, const char *file, int line,
const char *level_str, const char *format, ...)
{
va_list args;
char hugebuf[1024 * 2];
int res = 0;
if (ctx == NULL || ctx->log_cb == NULL)
return 1; /* silently drop message */
if (level > ctx->log_verbosity) /* excludes the case level is unknown */
return 1; /* suppress output since severity is not sufficient */
if (format == NULL)
return 0;
va_start(args, format);
if (func == NULL)
func = "(unset function name)";
if (file == NULL)
file = "(unset file name)";
if (level_str == NULL)
level_str = "(unset level string)";
#ifndef OPENSSL_NO_TRACE
if (OSSL_TRACE_ENABLED(CMP)) {
OSSL_TRACE_BEGIN(CMP) {
int printed =
BIO_snprintf(hugebuf, sizeof(hugebuf),
"%s:%s:%d:" OSSL_CMP_LOG_PREFIX "%s: ",
func, file, line, level_str);
if (printed > 0 && (size_t)printed < sizeof(hugebuf)) {
if (BIO_vsnprintf(hugebuf + printed,
sizeof(hugebuf) - printed, format, args) > 0)
res = BIO_puts(trc_out, hugebuf) > 0;
}
} OSSL_TRACE_END(CMP);
}
#else /* compensate for disabled trace API */
{
if (BIO_vsnprintf(hugebuf, sizeof(hugebuf), format, args) > 0)
res = ctx->log_cb(func, file, line, level, hugebuf);
}
#endif
va_end(args);
return res;
}
/* Set a callback function for error reporting and logging messages */
int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_log_cb_t cb)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx->log_cb = cb;
#ifndef OPENSSL_NO_TRACE
/* do also in case cb == NULL, to switch off logging output: */
if (!OSSL_trace_set_callback(OSSL_TRACE_CATEGORY_CMP,
ossl_cmp_log_trace_cb, ctx))
return 0;
#endif
return 1;
}
/* Print OpenSSL and CMP errors via the log cb of the ctx or ERR_print_errors */
void OSSL_CMP_CTX_print_errors(const OSSL_CMP_CTX *ctx)
{
if (ctx != NULL && OSSL_CMP_LOG_ERR > ctx->log_verbosity)
return; /* suppress output since severity is not sufficient */
OSSL_CMP_print_errors_cb(ctx == NULL ? NULL : ctx->log_cb);
}
/*
* Set or clear the reference value to be used for identification
* (i.e., the user name) when using PBMAC.
*/
int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx,
const unsigned char *ref, int len)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
return ossl_cmp_asn1_octet_string_set1_bytes(&ctx->referenceValue, ref,
len);
}
/* Set or clear the password to be used for protecting messages with PBMAC */
-int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, const unsigned char *sec,
- const int len)
+int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx,
+ const unsigned char *sec, int len)
{
ASN1_OCTET_STRING *secretValue = NULL;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (ossl_cmp_asn1_octet_string_set1_bytes(&secretValue, sec, len) != 1)
return 0;
if (ctx->secretValue != NULL) {
OPENSSL_cleanse(ctx->secretValue->data, ctx->secretValue->length);
ASN1_OCTET_STRING_free(ctx->secretValue);
}
ctx->secretValue = secretValue;
return 1;
}
/* Returns the cert chain computed by OSSL_CMP_certConf_cb(), NULL on error */
STACK_OF(X509) *OSSL_CMP_CTX_get1_newChain(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return X509_chain_up_ref(ctx->newChain);
}
/*
* Copies any given stack of inbound X509 certificates to newChain
* of the OSSL_CMP_CTX structure so that they may be retrieved later.
*/
int ossl_cmp_ctx_set1_newChain(OSSL_CMP_CTX *ctx, STACK_OF(X509) *newChain)
{
if (!ossl_assert(ctx != NULL))
return 0;
sk_X509_pop_free(ctx->newChain, X509_free);
ctx->newChain = NULL;
return newChain == NULL ||
(ctx->newChain = X509_chain_up_ref(newChain)) != NULL;
}
/* Returns the stack of extraCerts received in CertRepMessage, NULL on error */
STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return X509_chain_up_ref(ctx->extraCertsIn);
}
/*
* Copies any given stack of inbound X509 certificates to extraCertsIn
* of the OSSL_CMP_CTX structure so that they may be retrieved later.
*/
int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
STACK_OF(X509) *extraCertsIn)
{
if (!ossl_assert(ctx != NULL))
return 0;
sk_X509_pop_free(ctx->extraCertsIn, X509_free);
ctx->extraCertsIn = NULL;
return extraCertsIn == NULL
|| (ctx->extraCertsIn = X509_chain_up_ref(extraCertsIn)) != NULL;
}
/*
* Copies any given stack as the new stack of X509
* certificates to send out in the extraCerts field.
*/
int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx,
STACK_OF(X509) *extraCertsOut)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
sk_X509_pop_free(ctx->extraCertsOut, X509_free);
ctx->extraCertsOut = NULL;
return extraCertsOut == NULL
|| (ctx->extraCertsOut = X509_chain_up_ref(extraCertsOut)) != NULL;
}
/*
* Add the given policy info object
* to the X509_EXTENSIONS of the requested certificate template.
*/
int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo)
{
if (ctx == NULL || pinfo == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (ctx->policies == NULL
&& (ctx->policies = CERTIFICATEPOLICIES_new()) == NULL)
return 0;
return sk_POLICYINFO_push(ctx->policies, pinfo);
}
/* Add an ITAV for geninfo of the PKI message header */
int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
return OSSL_CMP_ITAV_push0_stack_item(&ctx->geninfo_ITAVs, itav);
}
int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
OSSL_CMP_ITAVs_free(ctx->geninfo_ITAVs);
ctx->geninfo_ITAVs = NULL;
return 1;
}
/* Add an itav for the body of outgoing general messages */
int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
return OSSL_CMP_ITAV_push0_stack_item(&ctx->genm_ITAVs, itav);
}
/*
* Returns a duplicate of the stack of X509 certificates that
* were received in the caPubs field of the last CertRepMessage.
* Returns NULL on error
*/
STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return X509_chain_up_ref(ctx->caPubs);
}
/*
* Copies any given stack of certificates to the given
* OSSL_CMP_CTX structure so that they may be retrieved later.
*/
int ossl_cmp_ctx_set1_caPubs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *caPubs)
{
if (!ossl_assert(ctx != NULL))
return 0;
sk_X509_pop_free(ctx->caPubs, X509_free);
ctx->caPubs = NULL;
return caPubs == NULL || (ctx->caPubs = X509_chain_up_ref(caPubs)) != NULL;
}
#define char_dup OPENSSL_strdup
#define char_free OPENSSL_free
#define DEFINE_OSSL_CMP_CTX_set1(FIELD, TYPE) /* this uses _dup */ \
int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, const TYPE *val) \
{ \
TYPE *val_dup = NULL; \
\
if (ctx == NULL) { \
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
return 0; \
} \
\
if (val != NULL && (val_dup = TYPE##_dup(val)) == NULL) \
return 0; \
TYPE##_free(ctx->FIELD); \
ctx->FIELD = val_dup; \
return 1; \
}
#define X509_invalid(cert) (!ossl_x509v3_cache_extensions(cert))
#define EVP_PKEY_invalid(key) 0
#define DEFINE_OSSL_CMP_CTX_set1_up_ref(FIELD, TYPE) \
int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, TYPE *val) \
{ \
if (ctx == NULL) { \
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
return 0; \
} \
\
/* prevent misleading error later on malformed cert or provider issue */ \
if (val != NULL && TYPE##_invalid(val)) { \
ERR_raise(ERR_LIB_CMP, CMP_R_POTENTIALLY_INVALID_CERTIFICATE); \
return 0; \
} \
if (val != NULL && !TYPE##_up_ref(val)) \
return 0; \
TYPE##_free(ctx->FIELD); \
ctx->FIELD = val; \
return 1; \
}
/*
* Pins the server certificate to be directly trusted (even if it is expired)
* for verifying response messages.
* Cert pointer is not consumed. It may be NULL to clear the entry.
*/
DEFINE_OSSL_CMP_CTX_set1_up_ref(srvCert, X509)
-/* Set the X509 name of the recipient. Set in the PKIHeader */
+/* Set the X509 name of the recipient to be placed in the PKIHeader */
DEFINE_OSSL_CMP_CTX_set1(recipient, X509_NAME)
/* Store the X509 name of the expected sender in the PKIHeader of responses */
DEFINE_OSSL_CMP_CTX_set1(expected_sender, X509_NAME)
-/* Set the X509 name of the issuer. Set in the PKIHeader */
+/* Set the X509 name of the issuer to be placed in the certTemplate */
DEFINE_OSSL_CMP_CTX_set1(issuer, X509_NAME)
/*
* Set the subject name that will be placed in the certificate
* request. This will be the subject name on the received certificate.
*/
DEFINE_OSSL_CMP_CTX_set1(subjectName, X509_NAME)
/* Set the X.509v3 certificate request extensions to be used in IR/CR/KUR */
int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (sk_GENERAL_NAME_num(ctx->subjectAltNames) > 0 && exts != NULL
&& X509v3_get_ext_by_NID(exts, NID_subject_alt_name, -1) >= 0) {
ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_SAN_SOURCES);
return 0;
}
sk_X509_EXTENSION_pop_free(ctx->reqExtensions, X509_EXTENSION_free);
ctx->reqExtensions = exts;
return 1;
}
/* returns 1 if ctx contains a Subject Alternative Name extension, else 0 */
int OSSL_CMP_CTX_reqExtensions_have_SAN(OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return -1;
}
/* if one of the following conditions 'fail' this is not an error */
return ctx->reqExtensions != NULL
&& X509v3_get_ext_by_NID(ctx->reqExtensions,
NID_subject_alt_name, -1) >= 0;
}
/*
* Add a GENERAL_NAME structure that will be added to the CRMF
* request's extensions field to request subject alternative names.
*/
int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
const GENERAL_NAME *name)
{
GENERAL_NAME *name_dup;
if (ctx == NULL || name == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) == 1) {
ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_SAN_SOURCES);
return 0;
}
if (ctx->subjectAltNames == NULL
&& (ctx->subjectAltNames = sk_GENERAL_NAME_new_null()) == NULL)
return 0;
if ((name_dup = GENERAL_NAME_dup(name)) == NULL)
return 0;
if (!sk_GENERAL_NAME_push(ctx->subjectAltNames, name_dup)) {
GENERAL_NAME_free(name_dup);
return 0;
}
return 1;
}
/*
* Set our own client certificate, used for example in KUR and when
* doing the IR with existing certificate.
*/
DEFINE_OSSL_CMP_CTX_set1_up_ref(cert, X509)
int OSSL_CMP_CTX_build_cert_chain(OSSL_CMP_CTX *ctx, X509_STORE *own_trusted,
STACK_OF(X509) *candidates)
{
STACK_OF(X509) *chain;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (!ossl_x509_add_certs_new(&ctx->untrusted, candidates,
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
return 0;
ossl_cmp_debug(ctx, "trying to build chain for own CMP signer cert");
chain = X509_build_chain(ctx->cert, ctx->untrusted, own_trusted, 0,
ctx->libctx, ctx->propq);
if (chain == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_FAILED_BUILDING_OWN_CHAIN);
return 0;
}
ossl_cmp_debug(ctx, "success building chain for own CMP signer cert");
ctx->chain = chain;
return 1;
}
/*
* Set the old certificate that we are updating in KUR
* or the certificate to be revoked in RR, respectively.
* Also used as reference cert (defaulting to cert) for deriving subject DN
* and SANs. Its issuer is used as default recipient in the CMP message header.
*/
DEFINE_OSSL_CMP_CTX_set1_up_ref(oldCert, X509)
/* Set the PKCS#10 CSR to be sent in P10CR */
DEFINE_OSSL_CMP_CTX_set1(p10CSR, X509_REQ)
/*
* Set the (newly received in IP/KUP/CP) certificate in the context.
* This only permits for one cert to be enrolled at a time.
*/
int ossl_cmp_ctx_set0_newCert(OSSL_CMP_CTX *ctx, X509 *cert)
{
if (!ossl_assert(ctx != NULL))
return 0;
X509_free(ctx->newCert);
ctx->newCert = cert;
return 1;
}
/*
* Get the (newly received in IP/KUP/CP) client certificate from the context
* This only permits for one client cert to be received...
*/
X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return ctx->newCert;
}
/* Set the client's current private key */
DEFINE_OSSL_CMP_CTX_set1_up_ref(pkey, EVP_PKEY)
/* Set new key pair. Used e.g. when doing Key Update */
int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
EVP_PKEY_free(ctx->newPkey);
ctx->newPkey = pkey;
ctx->newPkey_priv = priv;
return 1;
}
/* Get the private/public key to use for cert enrollment, or NULL on error */
+/* In case |priv| == 0, better use ossl_cmp_ctx_get0_newPubkey() below */
EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
if (ctx->newPkey != NULL)
return priv && !ctx->newPkey_priv ? NULL : ctx->newPkey;
if (ctx->p10CSR != NULL)
return priv ? NULL : X509_REQ_get0_pubkey(ctx->p10CSR);
return ctx->pkey; /* may be NULL */
}
+EVP_PKEY *ossl_cmp_ctx_get0_newPubkey(const OSSL_CMP_CTX *ctx)
+{
+ if (!ossl_assert(ctx != NULL))
+ return NULL;
+ if (ctx->newPkey != NULL)
+ return ctx->newPkey;
+ if (ctx->p10CSR != NULL)
+ return X509_REQ_get0_pubkey(ctx->p10CSR);
+ if (ctx->oldCert != NULL)
+ return X509_get0_pubkey(ctx->oldCert);
+ if (ctx->cert != NULL)
+ return X509_get0_pubkey(ctx->cert);
+ return ctx->pkey;
+}
+
/* Set the given transactionID to the context */
int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *id)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
return ossl_cmp_asn1_octet_string_set1(&ctx->transactionID, id);
}
/* Set the nonce to be used for the recipNonce in the message created next */
int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *nonce)
{
if (!ossl_assert(ctx != NULL))
return 0;
return ossl_cmp_asn1_octet_string_set1(&ctx->recipNonce, nonce);
}
/* Stores the given nonce as the last senderNonce sent out */
int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *nonce)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
return ossl_cmp_asn1_octet_string_set1(&ctx->senderNonce, nonce);
}
/* Set the proxy server to use for HTTP(S) connections */
DEFINE_OSSL_CMP_CTX_set1(proxy, char)
/* Set the (HTTP) host name of the CMP server */
DEFINE_OSSL_CMP_CTX_set1(server, char)
/* Set the server exclusion list of the HTTP proxy server */
DEFINE_OSSL_CMP_CTX_set1(no_proxy, char)
/* Set the http connect/disconnect callback function to be used for HTTP(S) */
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx->http_cb = cb;
return 1;
}
/* Set argument optionally to be used by the http connect/disconnect callback */
int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx->http_cb_arg = arg;
return 1;
}
/*
* Get argument optionally to be used by the http connect/disconnect callback
* Returns callback argument set previously (NULL if not set or on error)
*/
void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return ctx->http_cb_arg;
}
/* Set callback function for sending CMP request and receiving response */
int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_transfer_cb_t cb)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx->transfer_cb = cb;
return 1;
}
/* Set argument optionally to be used by the transfer callback */
int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx->transfer_cb_arg = arg;
return 1;
}
/*
* Get argument optionally to be used by the transfer callback.
* Returns callback argument set previously (NULL if not set or on error)
*/
void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return ctx->transfer_cb_arg;
}
/** Set the HTTP server port to be used */
int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx->serverPort = port;
return 1;
}
/* Set the HTTP path to be used on the server (e.g "pkix/") */
DEFINE_OSSL_CMP_CTX_set1(serverPath, char)
/* Set the failInfo error code as bit encoding in OSSL_CMP_CTX */
int ossl_cmp_ctx_set_failInfoCode(OSSL_CMP_CTX *ctx, int fail_info)
{
if (!ossl_assert(ctx != NULL))
return 0;
ctx->failInfoCode = fail_info;
return 1;
}
/*
* Get the failInfo error code in OSSL_CMP_CTX as bit encoding.
* Returns bit string as integer on success, -1 on error
*/
int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return -1;
}
return ctx->failInfoCode;
}
/* Set a Boolean or integer option of the context to the "val" arg */
int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
{
int min_val;
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
switch (opt) {
case OSSL_CMP_OPT_REVOCATION_REASON:
min_val = OCSP_REVOKED_STATUS_NOSTATUS;
break;
case OSSL_CMP_OPT_POPO_METHOD:
min_val = OSSL_CRMF_POPO_NONE;
break;
default:
min_val = 0;
break;
}
if (val < min_val) {
ERR_raise(ERR_LIB_CMP, CMP_R_VALUE_TOO_SMALL);
return 0;
}
switch (opt) {
case OSSL_CMP_OPT_LOG_VERBOSITY:
if (val > OSSL_CMP_LOG_MAX) {
ERR_raise(ERR_LIB_CMP, CMP_R_VALUE_TOO_LARGE);
return 0;
}
ctx->log_verbosity = val;
break;
case OSSL_CMP_OPT_IMPLICIT_CONFIRM:
ctx->implicitConfirm = val;
break;
case OSSL_CMP_OPT_DISABLE_CONFIRM:
ctx->disableConfirm = val;
break;
case OSSL_CMP_OPT_UNPROTECTED_SEND:
ctx->unprotectedSend = val;
break;
case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
ctx->unprotectedErrors = val;
break;
case OSSL_CMP_OPT_VALIDITY_DAYS:
ctx->days = val;
break;
case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:
ctx->SubjectAltName_nodefault = val;
break;
case OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL:
ctx->setSubjectAltNameCritical = val;
break;
case OSSL_CMP_OPT_POLICIES_CRITICAL:
ctx->setPoliciesCritical = val;
break;
case OSSL_CMP_OPT_IGNORE_KEYUSAGE:
ctx->ignore_keyusage = val;
break;
case OSSL_CMP_OPT_POPO_METHOD:
if (val > OSSL_CRMF_POPO_KEYAGREE) {
ERR_raise(ERR_LIB_CMP, CMP_R_VALUE_TOO_LARGE);
return 0;
}
ctx->popoMethod = val;
break;
case OSSL_CMP_OPT_DIGEST_ALGNID:
if (!cmp_ctx_set_md(ctx, &ctx->digest, val))
return 0;
break;
case OSSL_CMP_OPT_OWF_ALGNID:
if (!cmp_ctx_set_md(ctx, &ctx->pbm_owf, val))
return 0;
break;
case OSSL_CMP_OPT_MAC_ALGNID:
ctx->pbm_mac = val;
break;
case OSSL_CMP_OPT_KEEP_ALIVE:
ctx->keep_alive = val;
break;
case OSSL_CMP_OPT_MSG_TIMEOUT:
ctx->msg_timeout = val;
break;
case OSSL_CMP_OPT_TOTAL_TIMEOUT:
ctx->total_timeout = val;
break;
case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
ctx->permitTAInExtraCertsForIR = val;
break;
case OSSL_CMP_OPT_REVOCATION_REASON:
if (val > OCSP_REVOKED_STATUS_AACOMPROMISE) {
ERR_raise(ERR_LIB_CMP, CMP_R_VALUE_TOO_LARGE);
return 0;
}
ctx->revocationReason = val;
break;
default:
ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_OPTION);
return 0;
}
return 1;
}
/*
* Reads a Boolean or integer option value from the context.
* Returns -1 on error (which is the default OSSL_CMP_OPT_REVOCATION_REASON)
*/
int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return -1;
}
switch (opt) {
case OSSL_CMP_OPT_LOG_VERBOSITY:
return ctx->log_verbosity;
case OSSL_CMP_OPT_IMPLICIT_CONFIRM:
return ctx->implicitConfirm;
case OSSL_CMP_OPT_DISABLE_CONFIRM:
return ctx->disableConfirm;
case OSSL_CMP_OPT_UNPROTECTED_SEND:
return ctx->unprotectedSend;
case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
return ctx->unprotectedErrors;
case OSSL_CMP_OPT_VALIDITY_DAYS:
return ctx->days;
case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:
return ctx->SubjectAltName_nodefault;
case OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL:
return ctx->setSubjectAltNameCritical;
case OSSL_CMP_OPT_POLICIES_CRITICAL:
return ctx->setPoliciesCritical;
case OSSL_CMP_OPT_IGNORE_KEYUSAGE:
return ctx->ignore_keyusage;
case OSSL_CMP_OPT_POPO_METHOD:
return ctx->popoMethod;
case OSSL_CMP_OPT_DIGEST_ALGNID:
return EVP_MD_get_type(ctx->digest);
case OSSL_CMP_OPT_OWF_ALGNID:
return EVP_MD_get_type(ctx->pbm_owf);
case OSSL_CMP_OPT_MAC_ALGNID:
return ctx->pbm_mac;
case OSSL_CMP_OPT_KEEP_ALIVE:
return ctx->keep_alive;
case OSSL_CMP_OPT_MSG_TIMEOUT:
return ctx->msg_timeout;
case OSSL_CMP_OPT_TOTAL_TIMEOUT:
return ctx->total_timeout;
case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
return ctx->permitTAInExtraCertsForIR;
case OSSL_CMP_OPT_REVOCATION_REASON:
return ctx->revocationReason;
default:
ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_OPTION);
return -1;
}
}
diff --git a/crypto/cmp/cmp_err.c b/crypto/cmp/cmp_err.c
index fe7b96348bae..dfc6dfbedee9 100644
--- a/crypto/cmp/cmp_err.c
+++ b/crypto/cmp/cmp_err.c
@@ -1,178 +1,181 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <openssl/err.h>
#include <openssl/cmperr.h>
#include "crypto/cmperr.h"
#ifndef OPENSSL_NO_CMP
# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA CMP_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ALGORITHM_NOT_SUPPORTED),
"algorithm not supported"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_BAD_CHECKAFTER_IN_POLLREP),
"bad checkafter in pollrep"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_BAD_REQUEST_ID), "bad request id"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTHASH_UNMATCHED), "certhash unmatched"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTID_NOT_FOUND), "certid not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTIFICATE_NOT_ACCEPTED),
"certificate not accepted"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTIFICATE_NOT_FOUND),
"certificate not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTREQMSG_NOT_FOUND),
"certreqmsg not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTRESPONSE_NOT_FOUND),
"certresponse not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERT_AND_KEY_DO_NOT_MATCH),
"cert and key do not match"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CHECKAFTER_OUT_OF_RANGE),
"checkafter out of range"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ENCOUNTERED_KEYUPDATEWARNING),
"encountered keyupdatewarning"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ENCOUNTERED_WAITING),
"encountered waiting"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CALCULATING_PROTECTION),
"error calculating protection"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CERTCONF),
"error creating certconf"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CERTREP),
"error creating certrep"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CERTREQ),
"error creating certreq"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_ERROR),
"error creating error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_GENM),
"error creating genm"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_GENP),
"error creating genp"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_PKICONF),
"error creating pkiconf"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_POLLREP),
"error creating pollrep"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_POLLREQ),
"error creating pollreq"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_RP), "error creating rp"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_RR), "error creating rr"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PARSING_PKISTATUS),
"error parsing pkistatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PROCESSING_MESSAGE),
"error processing message"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PROTECTING_MESSAGE),
"error protecting message"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_SETTING_CERTHASH),
"error setting certhash"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_UNEXPECTED_CERTCONF),
"error unexpected certconf"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_PROTECTION),
"error validating protection"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_SIGNATURE),
"error validating signature"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_BUILDING_OWN_CHAIN),
"failed building own chain"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_PUBKEY),
"failed extracting pubkey"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILURE_OBTAINING_RANDOM),
"failure obtaining random"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAIL_INFO_OUT_OF_RANGE),
"fail info out of range"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ARGS), "invalid args"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_OPTION), "invalid option"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_CERTID), "missing certid"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION),
"missing key input for creating protection"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE),
"missing key usage digitalsignature"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_P10CSR), "missing p10csr"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_PBM_SECRET), "missing pbm secret"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_PRIVATE_KEY),
"missing private key"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_PRIVATE_KEY_FOR_POPO),
+ "missing private key for popo"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_PROTECTION), "missing protection"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_PUBLIC_KEY), "missing public key"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_REFERENCE_CERT),
"missing reference cert"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_SECRET), "missing secret"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_SENDER_IDENTIFICATION),
"missing sender identification"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_TRUST_ANCHOR),
"missing trust anchor"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_TRUST_STORE),
"missing trust store"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED),
"multiple requests not supported"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED),
"multiple responses not supported"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_SAN_SOURCES),
"multiple san sources"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NO_STDIO), "no stdio"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NO_SUITABLE_SENDER_CERT),
"no suitable sender cert"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NULL_ARGUMENT), "null argument"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_PKIBODY_ERROR), "pkibody error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_PKISTATUSINFO_NOT_FOUND),
"pkistatusinfo not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_POLLING_FAILED), "polling failed"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_POTENTIALLY_INVALID_CERTIFICATE),
"potentially invalid certificate"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_RECEIVED_ERROR), "received error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_RECIPNONCE_UNMATCHED),
"recipnonce unmatched"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_REQUEST_NOT_ACCEPTED),
"request not accepted"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_REQUEST_REJECTED_BY_SERVER),
"request rejected by server"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED),
"sender generalname type not supported"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG),
"srvcert does not validate msg"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TOTAL_TIMEOUT), "total timeout"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSACTIONID_UNMATCHED),
"transactionid unmatched"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSFER_ERROR), "transfer error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS),
"unexpected pkistatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PVNO), "unexpected pvno"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_ALGORITHM_ID),
"unknown algorithm id"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CERT_TYPE), "unknown cert type"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_PKISTATUS), "unknown pkistatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_ALGORITHM),
"unsupported algorithm"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_KEY_TYPE),
"unsupported key type"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC),
"unsupported protection alg dhbasedmac"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_VALUE_TOO_LARGE), "value too large"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_VALUE_TOO_SMALL), "value too small"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_ALGORITHM_OID),
"wrong algorithm oid"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_CERTID), "wrong certid"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_CERTID_IN_RP), "wrong certid in rp"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_PBM_VALUE), "wrong pbm value"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_RP_COMPONENT_COUNT),
"wrong rp component count"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_SERIAL_IN_RP), "wrong serial in rp"},
{0, NULL}
};
# endif
int ossl_err_load_CMP_strings(void)
{
# ifndef OPENSSL_NO_ERR
if (ERR_reason_error_string(CMP_str_reasons[0].error) == NULL)
ERR_load_strings_const(CMP_str_reasons);
# endif
return 1;
}
#else
NON_EMPTY_TRANSLATION_UNIT
#endif
diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h
index 3da021043b81..8eeb56d4e0f0 100644
--- a/crypto/cmp/cmp_local.h
+++ b/crypto/cmp/cmp_local.h
@@ -1,930 +1,933 @@
/*
- * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
#ifndef OSSL_CRYPTO_CMP_LOCAL_H
# define OSSL_CRYPTO_CMP_LOCAL_H
# include "internal/cryptlib.h"
# include <openssl/cmp.h>
# include <openssl/err.h>
/* explicit #includes not strictly needed since implied by the above: */
# include <openssl/crmf.h>
# include <openssl/types.h>
# include <openssl/safestack.h>
# include <openssl/x509.h>
# include <openssl/x509v3.h>
# include "crypto/x509.h"
#define IS_NULL_DN(name) (X509_NAME_get_entry(name, 0) == NULL)
/*
* this structure is used to store the context for CMP sessions
*/
struct ossl_cmp_ctx_st {
OSSL_LIB_CTX *libctx;
char *propq;
OSSL_CMP_log_cb_t log_cb; /* log callback for error/debug/etc. output */
OSSL_CMP_severity log_verbosity; /* level of verbosity of log output */
/* message transfer */
OSSL_CMP_transfer_cb_t transfer_cb; /* default: OSSL_CMP_MSG_http_perform */
void *transfer_cb_arg; /* allows to store optional argument to cb */
/* HTTP-based transfer */
OSSL_HTTP_REQ_CTX *http_ctx;
char *serverPath;
char *server;
int serverPort;
char *proxy;
char *no_proxy;
int keep_alive; /* persistent connection: 0=no, 1=prefer, 2=require */
int msg_timeout; /* max seconds to wait for each CMP message round trip */
int total_timeout; /* max number of seconds an enrollment may take, incl. */
/* attempts polling for a response if a 'waiting' PKIStatus is received */
time_t end_time; /* session start time + totaltimeout */
OSSL_HTTP_bio_cb_t http_cb;
void *http_cb_arg; /* allows to store optional argument to cb */
/* server authentication */
/*
* unprotectedErrors may be set as workaround for broken server responses:
* accept missing or invalid protection of regular error messages, negative
* certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf
*/
int unprotectedErrors;
X509 *srvCert; /* certificate used to identify the server */
X509 *validatedSrvCert; /* caches any already validated server cert */
X509_NAME *expected_sender; /* expected sender in header of response */
X509_STORE *trusted; /* trust store maybe w CRLs and cert verify callback */
STACK_OF(X509) *untrusted; /* untrusted (intermediate CA) certs */
int ignore_keyusage; /* ignore key usage entry when validating certs */
/*
* permitTAInExtraCertsForIR allows use of root certs in extracerts
* when validating message protection; this is used for 3GPP-style E.7
*/
int permitTAInExtraCertsForIR;
/* client authentication */
int unprotectedSend; /* send unprotected PKI messages */
X509 *cert; /* protection cert used to identify and sign for MSG_SIG_ALG */
STACK_OF(X509) *chain; /* (cached) chain of protection cert including it */
EVP_PKEY *pkey; /* the key pair corresponding to cert */
ASN1_OCTET_STRING *referenceValue; /* optional user name for MSG_MAC_ALG */
ASN1_OCTET_STRING *secretValue; /* password/shared secret for MSG_MAC_ALG */
/* PBMParameters for MSG_MAC_ALG */
size_t pbm_slen; /* salt length, currently fixed to 16 */
EVP_MD *pbm_owf; /* one-way function (OWF), default: SHA256 */
int pbm_itercnt; /* OWF iteration count, currently fixed to 500 */
int pbm_mac; /* NID of MAC algorithm, default: HMAC-SHA1 as per RFC 4210 */
/* CMP message header and extra certificates */
X509_NAME *recipient; /* to set in recipient in pkiheader */
EVP_MD *digest; /* digest used in MSG_SIG_ALG and POPO, default SHA256 */
ASN1_OCTET_STRING *transactionID; /* the current transaction ID */
ASN1_OCTET_STRING *senderNonce; /* last nonce sent */
ASN1_OCTET_STRING *recipNonce; /* last nonce received */
ASN1_UTF8STRING *freeText; /* optional string to include each msg */
STACK_OF(OSSL_CMP_ITAV) *geninfo_ITAVs;
int implicitConfirm; /* set implicitConfirm in IR/KUR/CR messages */
int disableConfirm; /* disable certConf in IR/KUR/CR for broken servers */
STACK_OF(X509) *extraCertsOut; /* to be included in request messages */
/* certificate template */
EVP_PKEY *newPkey; /* explicit new private/public key for cert enrollment */
int newPkey_priv; /* flag indicating if newPkey contains private key */
X509_NAME *issuer; /* issuer name to used in cert template */
int days; /* Number of days new certificates are asked to be valid for */
X509_NAME *subjectName; /* subject name to be used in cert template */
STACK_OF(GENERAL_NAME) *subjectAltNames; /* to add to the cert template */
int SubjectAltName_nodefault;
int setSubjectAltNameCritical;
X509_EXTENSIONS *reqExtensions; /* exts to be added to cert template */
CERTIFICATEPOLICIES *policies; /* policies to be included in extensions */
int setPoliciesCritical;
int popoMethod; /* Proof-of-possession mechanism; default: signature */
X509 *oldCert; /* cert to be updated (via KUR) or to be revoked (via RR) */
X509_REQ *p10CSR; /* for P10CR: PKCS#10 CSR to be sent */
/* misc body contents */
int revocationReason; /* revocation reason code to be included in RR */
STACK_OF(OSSL_CMP_ITAV) *genm_ITAVs; /* content of general message */
/* result returned in responses */
int status; /* PKIStatus of last received IP/CP/KUP/RP/error or -1 */
OSSL_CMP_PKIFREETEXT *statusString; /* of last IP/CP/KUP/RP/error */
int failInfoCode; /* failInfoCode of last received IP/CP/KUP/error, or -1 */
X509 *newCert; /* newly enrolled cert received from the CA */
STACK_OF(X509) *newChain; /* chain of newly enrolled cert received */
STACK_OF(X509) *caPubs; /* CA certs received from server (in IP message) */
STACK_OF(X509) *extraCertsIn; /* extraCerts received from server */
/* certificate confirmation */
OSSL_CMP_certConf_cb_t certConf_cb; /* callback for app checking new cert */
void *certConf_cb_arg; /* allows to store an argument individual to cb */
} /* OSSL_CMP_CTX */;
/*
* ##########################################################################
* ASN.1 DECLARATIONS
* ##########################################################################
*/
/*-
* RevAnnContent ::= SEQUENCE {
* status PKIStatus,
* certId CertId,
* willBeRevokedAt GeneralizedTime,
* badSinceDate GeneralizedTime,
* crlDetails Extensions OPTIONAL
* -- extra CRL details (e.g., crl number, reason, location, etc.)
* }
*/
typedef struct ossl_cmp_revanncontent_st {
ASN1_INTEGER *status;
OSSL_CRMF_CERTID *certId;
ASN1_GENERALIZEDTIME *willBeRevokedAt;
ASN1_GENERALIZEDTIME *badSinceDate;
X509_EXTENSIONS *crlDetails;
} OSSL_CMP_REVANNCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_REVANNCONTENT)
/*-
* Challenge ::= SEQUENCE {
* owf AlgorithmIdentifier OPTIONAL,
*
* -- MUST be present in the first Challenge; MAY be omitted in
* -- any subsequent Challenge in POPODecKeyChallContent (if
* -- omitted, then the owf used in the immediately preceding
* -- Challenge is to be used).
*
* witness OCTET STRING,
* -- the result of applying the one-way function (owf) to a
* -- randomly-generated INTEGER, A. [Note that a different
* -- INTEGER MUST be used for each Challenge.]
* challenge OCTET STRING
* -- the encryption (under the public key for which the cert.
* -- request is being made) of Rand, where Rand is specified as
* -- Rand ::= SEQUENCE {
* -- int INTEGER,
* -- - the randomly-generated INTEGER A (above)
* -- sender GeneralName
* -- - the sender's name (as included in PKIHeader)
* -- }
* }
*/
typedef struct ossl_cmp_challenge_st {
X509_ALGOR *owf;
ASN1_OCTET_STRING *witness;
ASN1_OCTET_STRING *challenge;
} OSSL_CMP_CHALLENGE;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CHALLENGE)
/*-
* CAKeyUpdAnnContent ::= SEQUENCE {
* oldWithNew Certificate,
* newWithOld Certificate,
* newWithNew Certificate
* }
*/
typedef struct ossl_cmp_cakeyupdanncontent_st {
X509 *oldWithNew;
X509 *newWithOld;
X509 *newWithNew;
} OSSL_CMP_CAKEYUPDANNCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT)
/*-
* declared already here as it will be used in OSSL_CMP_MSG (nested) and
* infoType and infoValue
*/
typedef STACK_OF(OSSL_CMP_MSG) OSSL_CMP_MSGS;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_MSGS)
/*-
* InfoTypeAndValue ::= SEQUENCE {
* infoType OBJECT IDENTIFIER,
* infoValue ANY DEFINED BY infoType OPTIONAL
* }
*/
struct ossl_cmp_itav_st {
ASN1_OBJECT *infoType;
union {
char *ptr;
/* NID_id_it_caProtEncCert - CA Protocol Encryption Certificate */
X509 *caProtEncCert;
/* NID_id_it_signKeyPairTypes - Signing Key Pair Types */
STACK_OF(X509_ALGOR) *signKeyPairTypes;
/* NID_id_it_encKeyPairTypes - Encryption/Key Agreement Key Pair Types */
STACK_OF(X509_ALGOR) *encKeyPairTypes;
/* NID_id_it_preferredSymmAlg - Preferred Symmetric Algorithm */
X509_ALGOR *preferredSymmAlg;
/* NID_id_it_caKeyUpdateInfo - Updated CA Key Pair */
OSSL_CMP_CAKEYUPDANNCONTENT *caKeyUpdateInfo;
/* NID_id_it_currentCRL - CRL */
X509_CRL *currentCRL;
/* NID_id_it_unsupportedOIDs - Unsupported Object Identifiers */
STACK_OF(ASN1_OBJECT) *unsupportedOIDs;
/* NID_id_it_keyPairParamReq - Key Pair Parameters Request */
ASN1_OBJECT *keyPairParamReq;
/* NID_id_it_keyPairParamRep - Key Pair Parameters Response */
X509_ALGOR *keyPairParamRep;
/* NID_id_it_revPassphrase - Revocation Passphrase */
OSSL_CRMF_ENCRYPTEDVALUE *revPassphrase;
/* NID_id_it_implicitConfirm - ImplicitConfirm */
ASN1_NULL *implicitConfirm;
/* NID_id_it_confirmWaitTime - ConfirmWaitTime */
ASN1_GENERALIZEDTIME *confirmWaitTime;
/* NID_id_it_origPKIMessage - origPKIMessage */
OSSL_CMP_MSGS *origPKIMessage;
/* NID_id_it_suppLangTags - Supported Language Tags */
STACK_OF(ASN1_UTF8STRING) *suppLangTagsValue;
/* this is to be used for so far undeclared objects */
ASN1_TYPE *other;
} infoValue;
} /* OSSL_CMP_ITAV */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ITAV)
typedef struct ossl_cmp_certorenccert_st {
int type;
union {
X509 *certificate;
OSSL_CRMF_ENCRYPTEDVALUE *encryptedCert;
} value;
} OSSL_CMP_CERTORENCCERT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTORENCCERT)
/*-
* CertifiedKeyPair ::= SEQUENCE {
* certOrEncCert CertOrEncCert,
* privateKey [0] EncryptedValue OPTIONAL,
* -- see [CRMF] for comment on encoding
* publicationInfo [1] PKIPublicationInfo OPTIONAL
* }
*/
typedef struct ossl_cmp_certifiedkeypair_st {
OSSL_CMP_CERTORENCCERT *certOrEncCert;
OSSL_CRMF_ENCRYPTEDVALUE *privateKey;
OSSL_CRMF_PKIPUBLICATIONINFO *publicationInfo;
} OSSL_CMP_CERTIFIEDKEYPAIR;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTIFIEDKEYPAIR)
/*-
* PKIStatusInfo ::= SEQUENCE {
* status PKIStatus,
* statusString PKIFreeText OPTIONAL,
* failInfo PKIFailureInfo OPTIONAL
* }
*/
struct ossl_cmp_pkisi_st {
OSSL_CMP_PKISTATUS *status;
OSSL_CMP_PKIFREETEXT *statusString;
OSSL_CMP_PKIFAILUREINFO *failInfo;
} /* OSSL_CMP_PKISI */;
/*-
* RevReqContent ::= SEQUENCE OF RevDetails
*
* RevDetails ::= SEQUENCE {
* certDetails CertTemplate,
* crlEntryDetails Extensions OPTIONAL
* }
*/
struct ossl_cmp_revdetails_st {
OSSL_CRMF_CERTTEMPLATE *certDetails;
X509_EXTENSIONS *crlEntryDetails;
} /* OSSL_CMP_REVDETAILS */;
typedef struct ossl_cmp_revdetails_st OSSL_CMP_REVDETAILS;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_REVDETAILS)
DEFINE_STACK_OF(OSSL_CMP_REVDETAILS)
/*-
* RevRepContent ::= SEQUENCE {
* status SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
* -- in same order as was sent in RevReqContent
* revCerts [0] SEQUENCE SIZE (1..MAX) OF CertId
* OPTIONAL,
* -- IDs for which revocation was requested
* -- (same order as status)
* crls [1] SEQUENCE SIZE (1..MAX) OF CertificateList
* OPTIONAL
* -- the resulting CRLs (there may be more than one)
* }
*/
struct ossl_cmp_revrepcontent_st {
STACK_OF(OSSL_CMP_PKISI) *status;
STACK_OF(OSSL_CRMF_CERTID) *revCerts;
STACK_OF(X509_CRL) *crls;
} /* OSSL_CMP_REVREPCONTENT */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_REVREPCONTENT)
/*-
* KeyRecRepContent ::= SEQUENCE {
* status PKIStatusInfo,
* newSigCert [0] Certificate OPTIONAL,
* caCerts [1] SEQUENCE SIZE (1..MAX) OF
* Certificate OPTIONAL,
* keyPairHist [2] SEQUENCE SIZE (1..MAX) OF
* CertifiedKeyPair OPTIONAL
* }
*/
typedef struct ossl_cmp_keyrecrepcontent_st {
OSSL_CMP_PKISI *status;
X509 *newSigCert;
STACK_OF(X509) *caCerts;
STACK_OF(OSSL_CMP_CERTIFIEDKEYPAIR) *keyPairHist;
} OSSL_CMP_KEYRECREPCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_KEYRECREPCONTENT)
/*-
* ErrorMsgContent ::= SEQUENCE {
* pKIStatusInfo PKIStatusInfo,
* errorCode INTEGER OPTIONAL,
* -- implementation-specific error codes
* errorDetails PKIFreeText OPTIONAL
* -- implementation-specific error details
* }
*/
typedef struct ossl_cmp_errormsgcontent_st {
OSSL_CMP_PKISI *pKIStatusInfo;
ASN1_INTEGER *errorCode;
OSSL_CMP_PKIFREETEXT *errorDetails;
} OSSL_CMP_ERRORMSGCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ERRORMSGCONTENT)
/*-
* CertConfirmContent ::= SEQUENCE OF CertStatus
*
* CertStatus ::= SEQUENCE {
* certHash OCTET STRING,
* -- the hash of the certificate, using the same hash algorithm
* -- as is used to create and verify the certificate signature
* certReqId INTEGER,
* -- to match this confirmation with the corresponding req/rep
* statusInfo PKIStatusInfo OPTIONAL
* }
*/
struct ossl_cmp_certstatus_st {
ASN1_OCTET_STRING *certHash;
ASN1_INTEGER *certReqId;
OSSL_CMP_PKISI *statusInfo;
} /* OSSL_CMP_CERTSTATUS */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTSTATUS)
typedef STACK_OF(OSSL_CMP_CERTSTATUS) OSSL_CMP_CERTCONFIRMCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTCONFIRMCONTENT)
/*-
* CertResponse ::= SEQUENCE {
* certReqId INTEGER,
* -- to match this response with corresponding request (a value
* -- of -1 is to be used if certReqId is not specified in the
* -- corresponding request)
* status PKIStatusInfo,
* certifiedKeyPair CertifiedKeyPair OPTIONAL,
* rspInfo OCTET STRING OPTIONAL
* -- analogous to the id-regInfo-utf8Pairs string defined
* -- for regInfo in CertReqMsg [CRMF]
* }
*/
struct ossl_cmp_certresponse_st {
ASN1_INTEGER *certReqId;
OSSL_CMP_PKISI *status;
OSSL_CMP_CERTIFIEDKEYPAIR *certifiedKeyPair;
ASN1_OCTET_STRING *rspInfo;
} /* OSSL_CMP_CERTRESPONSE */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTRESPONSE)
/*-
* CertRepMessage ::= SEQUENCE {
* caPubs [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
* OPTIONAL,
* response SEQUENCE OF CertResponse
* }
*/
struct ossl_cmp_certrepmessage_st {
STACK_OF(X509) *caPubs;
STACK_OF(OSSL_CMP_CERTRESPONSE) *response;
} /* OSSL_CMP_CERTREPMESSAGE */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTREPMESSAGE)
/*-
* PollReqContent ::= SEQUENCE OF SEQUENCE {
* certReqId INTEGER
* }
*/
typedef struct ossl_cmp_pollreq_st {
ASN1_INTEGER *certReqId;
} OSSL_CMP_POLLREQ;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POLLREQ)
DEFINE_STACK_OF(OSSL_CMP_POLLREQ)
typedef STACK_OF(OSSL_CMP_POLLREQ) OSSL_CMP_POLLREQCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POLLREQCONTENT)
/*-
* PollRepContent ::= SEQUENCE OF SEQUENCE {
* certReqId INTEGER,
* checkAfter INTEGER, -- time in seconds
* reason PKIFreeText OPTIONAL
* }
*/
struct ossl_cmp_pollrep_st {
ASN1_INTEGER *certReqId;
ASN1_INTEGER *checkAfter;
OSSL_CMP_PKIFREETEXT *reason;
} /* OSSL_CMP_POLLREP */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POLLREP)
DEFINE_STACK_OF(OSSL_CMP_POLLREP)
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POLLREPCONTENT)
/*-
* PKIHeader ::= SEQUENCE {
* pvno INTEGER { cmp1999(1), cmp2000(2) },
* sender GeneralName,
* -- identifies the sender
* recipient GeneralName,
* -- identifies the intended recipient
* messageTime [0] GeneralizedTime OPTIONAL,
* -- time of production of this message (used when sender
* -- believes that the transport will be "suitable"; i.e.,
* -- that the time will still be meaningful upon receipt)
* protectionAlg [1] AlgorithmIdentifier OPTIONAL,
* -- algorithm used for calculation of protection bits
* senderKID [2] KeyIdentifier OPTIONAL,
* recipKID [3] KeyIdentifier OPTIONAL,
* -- to identify specific keys used for protection
* transactionID [4] OCTET STRING OPTIONAL,
* -- identifies the transaction; i.e., this will be the same in
* -- corresponding request, response, certConf, and PKIConf
* -- messages
* senderNonce [5] OCTET STRING OPTIONAL,
* recipNonce [6] OCTET STRING OPTIONAL,
* -- nonces used to provide replay protection, senderNonce
* -- is inserted by the creator of this message; recipNonce
* -- is a nonce previously inserted in a related message by
* -- the intended recipient of this message
* freeText [7] PKIFreeText OPTIONAL,
* -- this may be used to indicate context-specific instructions
* -- (this field is intended for human consumption)
* generalInfo [8] SEQUENCE SIZE (1..MAX) OF
* InfoTypeAndValue OPTIONAL
* -- this may be used to convey context-specific information
* -- (this field not primarily intended for human consumption)
* }
*/
struct ossl_cmp_pkiheader_st {
ASN1_INTEGER *pvno;
GENERAL_NAME *sender;
GENERAL_NAME *recipient;
ASN1_GENERALIZEDTIME *messageTime; /* 0 */
X509_ALGOR *protectionAlg; /* 1 */
ASN1_OCTET_STRING *senderKID; /* 2 */
ASN1_OCTET_STRING *recipKID; /* 3 */
ASN1_OCTET_STRING *transactionID; /* 4 */
ASN1_OCTET_STRING *senderNonce; /* 5 */
ASN1_OCTET_STRING *recipNonce; /* 6 */
OSSL_CMP_PKIFREETEXT *freeText; /* 7 */
STACK_OF(OSSL_CMP_ITAV) *generalInfo; /* 8 */
} /* OSSL_CMP_PKIHEADER */;
typedef STACK_OF(OSSL_CMP_CHALLENGE) OSSL_CMP_POPODECKEYCHALLCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POPODECKEYCHALLCONTENT)
typedef STACK_OF(ASN1_INTEGER) OSSL_CMP_POPODECKEYRESPCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POPODECKEYRESPCONTENT)
typedef STACK_OF(OSSL_CMP_REVDETAILS) OSSL_CMP_REVREQCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_REVREQCONTENT)
typedef STACK_OF(X509_CRL) OSSL_CMP_CRLANNCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CRLANNCONTENT)
typedef STACK_OF(OSSL_CMP_ITAV) OSSL_CMP_GENMSGCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_GENMSGCONTENT)
typedef STACK_OF(OSSL_CMP_ITAV) OSSL_CMP_GENREPCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_GENREPCONTENT)
/*-
* PKIBody ::= CHOICE { -- message-specific body elements
* ir [0] CertReqMessages, --Initialization Request
* ip [1] CertRepMessage, --Initialization Response
* cr [2] CertReqMessages, --Certification Request
* cp [3] CertRepMessage, --Certification Response
* p10cr [4] CertificationRequest, --imported from [PKCS10]
* popdecc [5] POPODecKeyChallContent, --pop Challenge
* popdecr [6] POPODecKeyRespContent, --pop Response
* kur [7] CertReqMessages, --Key Update Request
* kup [8] CertRepMessage, --Key Update Response
* krr [9] CertReqMessages, --Key Recovery Request
* krp [10] KeyRecRepContent, --Key Recovery Response
* rr [11] RevReqContent, --Revocation Request
* rp [12] RevRepContent, --Revocation Response
* ccr [13] CertReqMessages, --Cross-Cert. Request
* ccp [14] CertRepMessage, --Cross-Cert. Response
* ckuann [15] CAKeyUpdAnnContent, --CA Key Update Ann.
* cann [16] CertAnnContent, --Certificate Ann.
* rann [17] RevAnnContent, --Revocation Ann.
* crlann [18] CRLAnnContent, --CRL Announcement
* pkiconf [19] PKIConfirmContent, --Confirmation
* nested [20] NestedMessageContent, --Nested Message
* genm [21] GenMsgContent, --General Message
* genp [22] GenRepContent, --General Response
* error [23] ErrorMsgContent, --Error Message
* certConf [24] CertConfirmContent, --Certificate confirm
* pollReq [25] PollReqContent, --Polling request
* pollRep [26] PollRepContent --Polling response
* }
*/
typedef struct ossl_cmp_pkibody_st {
int type;
union {
OSSL_CRMF_MSGS *ir; /* 0 */
OSSL_CMP_CERTREPMESSAGE *ip; /* 1 */
OSSL_CRMF_MSGS *cr; /* 2 */
OSSL_CMP_CERTREPMESSAGE *cp; /* 3 */
/*-
* p10cr [4] CertificationRequest, --imported from [PKCS10]
*
* PKCS10_CERTIFICATIONREQUEST is effectively X509_REQ
* so it is used directly
*/
X509_REQ *p10cr; /* 4 */
/*-
* popdecc [5] POPODecKeyChallContent, --pop Challenge
*
* POPODecKeyChallContent ::= SEQUENCE OF Challenge
*/
OSSL_CMP_POPODECKEYCHALLCONTENT *popdecc; /* 5 */
/*-
* popdecr [6] POPODecKeyRespContent, --pop Response
*
* POPODecKeyRespContent ::= SEQUENCE OF INTEGER
*/
OSSL_CMP_POPODECKEYRESPCONTENT *popdecr; /* 6 */
OSSL_CRMF_MSGS *kur; /* 7 */
OSSL_CMP_CERTREPMESSAGE *kup; /* 8 */
OSSL_CRMF_MSGS *krr; /* 9 */
/*-
* krp [10] KeyRecRepContent, --Key Recovery Response
*/
OSSL_CMP_KEYRECREPCONTENT *krp; /* 10 */
/*-
* rr [11] RevReqContent, --Revocation Request
*/
OSSL_CMP_REVREQCONTENT *rr; /* 11 */
/*-
* rp [12] RevRepContent, --Revocation Response
*/
OSSL_CMP_REVREPCONTENT *rp; /* 12 */
/*-
* ccr [13] CertReqMessages, --Cross-Cert. Request
*/
OSSL_CRMF_MSGS *ccr; /* 13 */
/*-
* ccp [14] CertRepMessage, --Cross-Cert. Response
*/
OSSL_CMP_CERTREPMESSAGE *ccp; /* 14 */
/*-
* ckuann [15] CAKeyUpdAnnContent, --CA Key Update Ann.
*/
OSSL_CMP_CAKEYUPDANNCONTENT *ckuann; /* 15 */
/*-
* cann [16] CertAnnContent, --Certificate Ann.
* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly
*/
X509 *cann; /* 16 */
/*-
* rann [17] RevAnnContent, --Revocation Ann.
*/
OSSL_CMP_REVANNCONTENT *rann; /* 17 */
/*-
* crlann [18] CRLAnnContent, --CRL Announcement
* CRLAnnContent ::= SEQUENCE OF CertificateList
*/
OSSL_CMP_CRLANNCONTENT *crlann; /* 18 */
/*-
* PKIConfirmContent ::= NULL
* pkiconf [19] PKIConfirmContent, --Confirmation
* OSSL_CMP_PKICONFIRMCONTENT would be only a typedef of ASN1_NULL
* OSSL_CMP_CONFIRMCONTENT *pkiconf;
*
* NOTE: this should ASN1_NULL according to the RFC
* but there might be a struct in it when sent from faulty servers...
*/
ASN1_TYPE *pkiconf; /* 19 */
/*-
* nested [20] NestedMessageContent, --Nested Message
* NestedMessageContent ::= PKIMessages
*/
OSSL_CMP_MSGS *nested; /* 20 */
/*-
* genm [21] GenMsgContent, --General Message
* GenMsgContent ::= SEQUENCE OF InfoTypeAndValue
*/
OSSL_CMP_GENMSGCONTENT *genm; /* 21 */
/*-
* genp [22] GenRepContent, --General Response
* GenRepContent ::= SEQUENCE OF InfoTypeAndValue
*/
OSSL_CMP_GENREPCONTENT *genp; /* 22 */
/*-
* error [23] ErrorMsgContent, --Error Message
*/
OSSL_CMP_ERRORMSGCONTENT *error; /* 23 */
/*-
* certConf [24] CertConfirmContent, --Certificate confirm
*/
OSSL_CMP_CERTCONFIRMCONTENT *certConf; /* 24 */
/*-
* pollReq [25] PollReqContent, --Polling request
*/
OSSL_CMP_POLLREQCONTENT *pollReq; /* 25 */
/*-
* pollRep [26] PollRepContent --Polling response
*/
OSSL_CMP_POLLREPCONTENT *pollRep; /* 26 */
} value;
} OSSL_CMP_PKIBODY;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKIBODY)
/*-
* PKIProtection ::= BIT STRING
*
* PKIMessages ::= SEQUENCE SIZE (1..MAX) OF PKIMessage
*
* PKIMessage ::= SEQUENCE {
* header PKIHeader,
* body PKIBody,
* protection [0] PKIProtection OPTIONAL,
* extraCerts [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
* OPTIONAL
* }
*/
struct ossl_cmp_msg_st {
OSSL_CMP_PKIHEADER *header;
OSSL_CMP_PKIBODY *body;
ASN1_BIT_STRING *protection; /* 0 */
/* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
STACK_OF(X509) *extraCerts; /* 1 */
OSSL_LIB_CTX *libctx;
char *propq;
} /* OSSL_CMP_MSG */;
OSSL_CMP_MSG *OSSL_CMP_MSG_new(OSSL_LIB_CTX *libctx, const char *propq);
void OSSL_CMP_MSG_free(OSSL_CMP_MSG *msg);
/*-
* ProtectedPart ::= SEQUENCE {
* header PKIHeader,
* body PKIBody
* }
*/
typedef struct ossl_cmp_protectedpart_st {
OSSL_CMP_PKIHEADER *header;
OSSL_CMP_PKIBODY *body;
} OSSL_CMP_PROTECTEDPART;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PROTECTEDPART)
/*-
* this is not defined here as it is already in CRMF:
* id-PasswordBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 13}
* PBMParameter ::= SEQUENCE {
* salt OCTET STRING,
* -- note: implementations MAY wish to limit acceptable sizes
* -- of this string to values appropriate for their environment
* -- in order to reduce the risk of denial-of-service attacks
* owf AlgorithmIdentifier,
* -- AlgId for a One-Way Function (SHA-1 recommended)
* iterationCount INTEGER,
* -- number of times the OWF is applied
* -- note: implementations MAY wish to limit acceptable sizes
* -- of this integer to values appropriate for their environment
* -- in order to reduce the risk of denial-of-service attacks
* mac AlgorithmIdentifier
* -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
* } -- or HMAC [RFC2104, RFC2202])
*/
/*-
* id-DHBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 30}
* DHBMParameter ::= SEQUENCE {
* owf AlgorithmIdentifier,
* -- AlgId for a One-Way Function (SHA-1 recommended)
* mac AlgorithmIdentifier
* -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
* } -- or HMAC [RFC2104, RFC2202])
*/
/*-
* The following is not cared for, because it is described in section 5.2.5
* that this is beyond the scope of CMP
* OOBCert ::= CMPCertificate
*
* OOBCertHash ::= SEQUENCE {
* hashAlg [0] AlgorithmIdentifier OPTIONAL,
* certId [1] CertId OPTIONAL,
* hashVal BIT STRING
* -- hashVal is calculated over the DER encoding of the
* -- self-signed certificate with the identifier certID.
* }
*/
/* from cmp_asn.c */
int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a);
/* from cmp_util.c */
const char *ossl_cmp_log_parse_metadata(const char *buf,
OSSL_CMP_severity *level, char **func,
char **file, int *line);
# define ossl_cmp_add_error_data(txt) ERR_add_error_txt(" : ", txt)
# define ossl_cmp_add_error_line(txt) ERR_add_error_txt("\n", txt)
/* The two functions manipulating X509_STORE could be generally useful */
int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
int only_self_issued);
STACK_OF(X509) *ossl_cmp_X509_STORE_get1_certs(X509_STORE *store);
int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk,
const char *text, int len);
int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
const ASN1_OCTET_STRING *src);
int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt,
const unsigned char *bytes, int len);
/* from cmp_ctx.c */
int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx,
const char *func, const char *file, int line,
const char *level_str, const char *format, ...);
# define ossl_cmp_log(level, ctx, msg) \
ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
OPENSSL_LINE, #level, "%s", msg)
# define ossl_cmp_log1(level, ctx, fmt, arg1) \
ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
OPENSSL_LINE, #level, fmt, arg1)
# define ossl_cmp_log2(level, ctx, fmt, arg1, arg2) \
ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
OPENSSL_LINE, #level, fmt, arg1, arg2)
# define ossl_cmp_log3(level, ctx, fmt, arg1, arg2, arg3) \
ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
OPENSSL_LINE, #level, fmt, arg1, arg2, arg3)
# define ossl_cmp_log4(level, ctx, fmt, arg1, arg2, arg3, arg4) \
ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
OPENSSL_LINE, #level, fmt, arg1, arg2, arg3, arg4)
# define OSSL_CMP_LOG_ERROR OSSL_CMP_LOG_ERR
# define OSSL_CMP_LOG_WARN OSSL_CMP_LOG_WARNING
# define ossl_cmp_alert(ctx, msg) ossl_cmp_log(ALERT, ctx, msg)
# define ossl_cmp_err(ctx, msg) ossl_cmp_log(ERROR, ctx, msg)
# define ossl_cmp_warn(ctx, msg) ossl_cmp_log(WARN, ctx, msg)
# define ossl_cmp_info(ctx, msg) ossl_cmp_log(INFO, ctx, msg)
# define ossl_cmp_debug(ctx, msg) ossl_cmp_log(DEBUG, ctx, msg)
# define ossl_cmp_trace(ctx, msg) ossl_cmp_log(TRACE, ctx, msg)
int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert);
int ossl_cmp_ctx_set_status(OSSL_CMP_CTX *ctx, int status);
int ossl_cmp_ctx_set0_statusString(OSSL_CMP_CTX *ctx,
OSSL_CMP_PKIFREETEXT *text);
int ossl_cmp_ctx_set_failInfoCode(OSSL_CMP_CTX *ctx, int fail_info);
int ossl_cmp_ctx_set0_newCert(OSSL_CMP_CTX *ctx, X509 *cert);
int ossl_cmp_ctx_set1_newChain(OSSL_CMP_CTX *ctx, STACK_OF(X509) *newChain);
int ossl_cmp_ctx_set1_caPubs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *caPubs);
int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
STACK_OF(X509) *extraCertsIn);
int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *nonce);
+EVP_PKEY *ossl_cmp_ctx_get0_newPubkey(const OSSL_CMP_CTX *ctx);
/* from cmp_status.c */
int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si);
const char *ossl_cmp_PKIStatus_to_string(int status);
OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusString(const OSSL_CMP_PKISI *s);
int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si);
int ossl_cmp_pkisi_check_pkifailureinfo(const OSSL_CMP_PKISI *si, int index);
/* from cmp_hdr.c */
int ossl_cmp_hdr_set_pvno(OSSL_CMP_PKIHEADER *hdr, int pvno);
int ossl_cmp_hdr_get_pvno(const OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_hdr_get_protection_nid(const OSSL_CMP_PKIHEADER *hdr);
ASN1_OCTET_STRING *ossl_cmp_hdr_get0_senderNonce(const OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name);
int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm);
int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm);
int ossl_cmp_hdr_update_messageTime(OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_hdr_set1_senderKID(OSSL_CMP_PKIHEADER *hdr,
const ASN1_OCTET_STRING *senderKID);
int ossl_cmp_hdr_push0_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text);
int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text);
int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr,
OSSL_CMP_ITAV *itav);
int ossl_cmp_hdr_generalInfo_push1_items(OSSL_CMP_PKIHEADER *hdr,
const STACK_OF(OSSL_CMP_ITAV) *itavs);
int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_hdr_has_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr);
# define OSSL_CMP_TRANSACTIONID_LENGTH 16
# define OSSL_CMP_SENDERNONCE_LENGTH 16
int ossl_cmp_hdr_set_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr);
/* from cmp_msg.c */
/* OSSL_CMP_MSG bodytype ASN.1 choice IDs */
# define OSSL_CMP_PKIBODY_IR 0
# define OSSL_CMP_PKIBODY_IP 1
# define OSSL_CMP_PKIBODY_CR 2
# define OSSL_CMP_PKIBODY_CP 3
# define OSSL_CMP_PKIBODY_P10CR 4
# define OSSL_CMP_PKIBODY_POPDECC 5
# define OSSL_CMP_PKIBODY_POPDECR 6
# define OSSL_CMP_PKIBODY_KUR 7
# define OSSL_CMP_PKIBODY_KUP 8
# define OSSL_CMP_PKIBODY_KRR 9
# define OSSL_CMP_PKIBODY_KRP 10
# define OSSL_CMP_PKIBODY_RR 11
# define OSSL_CMP_PKIBODY_RP 12
# define OSSL_CMP_PKIBODY_CCR 13
# define OSSL_CMP_PKIBODY_CCP 14
# define OSSL_CMP_PKIBODY_CKUANN 15
# define OSSL_CMP_PKIBODY_CANN 16
# define OSSL_CMP_PKIBODY_RANN 17
# define OSSL_CMP_PKIBODY_CRLANN 18
# define OSSL_CMP_PKIBODY_PKICONF 19
# define OSSL_CMP_PKIBODY_NESTED 20
# define OSSL_CMP_PKIBODY_GENM 21
# define OSSL_CMP_PKIBODY_GENP 22
# define OSSL_CMP_PKIBODY_ERROR 23
# define OSSL_CMP_PKIBODY_CERTCONF 24
# define OSSL_CMP_PKIBODY_POLLREQ 25
# define OSSL_CMP_PKIBODY_POLLREP 26
# define OSSL_CMP_PKIBODY_TYPE_MAX OSSL_CMP_PKIBODY_POLLREP
/* certReqId for the first - and so far only - certificate request */
-# define OSSL_CMP_CERTREQID 0
+# define OSSL_CMP_CERTREQID 0
+# define OSSL_CMP_CERTREQID_NONE -1
+# define OSSL_CMP_CERTREQID_INVALID -2
/* sequence id for the first - and so far only - revocation request */
# define OSSL_CMP_REVREQSID 0
int ossl_cmp_msg_set0_libctx(OSSL_CMP_MSG *msg, OSSL_LIB_CTX *libctx,
const char *propq);
const char *ossl_cmp_bodytype_to_string(int type);
int ossl_cmp_msg_set_bodytype(OSSL_CMP_MSG *msg, int type);
OSSL_CMP_MSG *ossl_cmp_msg_create(OSSL_CMP_CTX *ctx, int bodytype);
OSSL_CMP_MSG *ossl_cmp_certreq_new(OSSL_CMP_CTX *ctx, int bodytype,
const OSSL_CRMF_MSG *crm);
OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
int certReqId, const OSSL_CMP_PKISI *si,
X509 *cert, const X509 *encryption_recip,
STACK_OF(X509) *chain, STACK_OF(X509) *caPubs,
int unprotectedErrors);
OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
const OSSL_CRMF_CERTID *cid,
int unprotectedErrors);
OSSL_CMP_MSG *ossl_cmp_pkiconf_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
int64_t poll_after);
int ossl_cmp_msg_gen_push0_ITAV(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav);
int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
const STACK_OF(OSSL_CMP_ITAV) *itavs);
OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx,
const STACK_OF(OSSL_CMP_ITAV) *itavs);
OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
int64_t errorCode, const char *details,
int unprotected);
int ossl_cmp_certstatus_set0_certHash(OSSL_CMP_CERTSTATUS *certStatus,
ASN1_OCTET_STRING *hash);
-OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
- const char *text);
+OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int certReqId,
+ int fail_info, const char *text);
OSSL_CMP_MSG *ossl_cmp_pollReq_new(OSSL_CMP_CTX *ctx, int crid);
OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
int64_t poll_after);
OSSL_CMP_PKISI *
ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid);
OSSL_CRMF_CERTID *ossl_cmp_revrepcontent_get_CertId(OSSL_CMP_REVREPCONTENT *rc,
int rsid);
OSSL_CMP_POLLREP *
ossl_cmp_pollrepcontent_get0_pollrep(const OSSL_CMP_POLLREPCONTENT *prc,
int rid);
OSSL_CMP_CERTRESPONSE *
ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
int rid);
-X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CERTRESPONSE *crep,
- const OSSL_CMP_CTX *ctx, EVP_PKEY *pkey);
+X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_CERTRESPONSE *crep);
OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file);
/* from cmp_protect.c */
int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *msg);
int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
/* from cmp_vfy.c */
typedef int (*ossl_cmp_allow_unprotected_cb_t)(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *msg,
int invalid_protection, int arg);
int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
ossl_cmp_allow_unprotected_cb_t cb, int cb_arg);
int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
ossl_cmp_allow_unprotected_cb_t cb, int cb_arg);
int ossl_cmp_verify_popo(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *msg, int accept_RAVerified);
/* from cmp_client.c */
-int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int fail_info,
- const char *txt);
+int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int certReqId,
+ int fail_info, const char *txt);
int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info,
const char *txt, int errorCode, const char *detail);
#endif /* !defined(OSSL_CRYPTO_CMP_LOCAL_H) */
diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c
index b244f1e17f0d..c8e467f3c21f 100644
--- a/crypto/cmp/cmp_msg.c
+++ b/crypto/cmp/cmp_msg.c
@@ -1,1170 +1,1180 @@
/*
- * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/* CMP functions for PKIMessage construction */
#include "cmp_local.h"
/* explicit #includes not strictly needed since implied by the above: */
#include <openssl/asn1t.h>
#include <openssl/cmp.h>
#include <openssl/crmf.h>
#include <openssl/err.h>
#include <openssl/x509.h>
OSSL_CMP_MSG *OSSL_CMP_MSG_new(OSSL_LIB_CTX *libctx, const char *propq)
{
OSSL_CMP_MSG *msg = NULL;
msg = (OSSL_CMP_MSG *)ASN1_item_new_ex(ASN1_ITEM_rptr(OSSL_CMP_MSG),
libctx, propq);
if (!ossl_cmp_msg_set0_libctx(msg, libctx, propq)) {
OSSL_CMP_MSG_free(msg);
msg = NULL;
}
return msg;
}
void OSSL_CMP_MSG_free(OSSL_CMP_MSG *msg)
{
ASN1_item_free((ASN1_VALUE *)msg, ASN1_ITEM_rptr(OSSL_CMP_MSG));
}
/*
* This should only be used if the X509 object was embedded inside another
* asn1 object and it needs a libctx to operate.
* Use OSSL_CMP_MSG_new() instead if possible.
*/
int ossl_cmp_msg_set0_libctx(OSSL_CMP_MSG *msg, OSSL_LIB_CTX *libctx,
const char *propq)
{
if (msg != NULL) {
msg->libctx = libctx;
OPENSSL_free(msg->propq);
msg->propq = NULL;
if (propq != NULL) {
msg->propq = OPENSSL_strdup(propq);
if (msg->propq == NULL)
return 0;
}
}
return 1;
}
OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg)
{
if (msg == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return msg->header;
}
const char *ossl_cmp_bodytype_to_string(int type)
{
static const char *type_names[] = {
"IR", "IP", "CR", "CP", "P10CR",
"POPDECC", "POPDECR", "KUR", "KUP",
"KRR", "KRP", "RR", "RP", "CCR", "CCP",
"CKUANN", "CANN", "RANN", "CRLANN", "PKICONF", "NESTED",
"GENM", "GENP", "ERROR", "CERTCONF", "POLLREQ", "POLLREP",
};
if (type < 0 || type > OSSL_CMP_PKIBODY_TYPE_MAX)
return "illegal body type";
return type_names[type];
}
int ossl_cmp_msg_set_bodytype(OSSL_CMP_MSG *msg, int type)
{
if (!ossl_assert(msg != NULL && msg->body != NULL))
return 0;
msg->body->type = type;
return 1;
}
int OSSL_CMP_MSG_get_bodytype(const OSSL_CMP_MSG *msg)
{
if (!ossl_assert(msg != NULL && msg->body != NULL))
return -1;
return msg->body->type;
}
/* Add an extension to the referenced extension stack, which may be NULL */
static int add1_extension(X509_EXTENSIONS **pexts, int nid, int crit, void *ex)
{
X509_EXTENSION *ext;
int res;
if (!ossl_assert(pexts != NULL)) /* pointer to var must not be NULL */
return 0;
if ((ext = X509V3_EXT_i2d(nid, crit, ex)) == NULL)
return 0;
res = X509v3_add_ext(pexts, ext, 0) != NULL;
X509_EXTENSION_free(ext);
return res;
}
/* Add extension list to the referenced extension stack, which may be NULL */
static int add_extensions(STACK_OF(X509_EXTENSION) **target,
const STACK_OF(X509_EXTENSION) *exts)
{
int i;
if (target == NULL)
return 0;
for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext);
int idx = X509v3_get_ext_by_OBJ(*target, obj, -1);
/* Does extension exist in target? */
if (idx != -1) {
/* Delete all extensions of same type */
do {
X509_EXTENSION_free(sk_X509_EXTENSION_delete(*target, idx));
idx = X509v3_get_ext_by_OBJ(*target, obj, -1);
} while (idx != -1);
}
if (!X509v3_add_ext(target, ext, -1))
return 0;
}
return 1;
}
/* Add a CRL revocation reason code to extension stack, which may be NULL */
static int add_crl_reason_extension(X509_EXTENSIONS **pexts, int reason_code)
{
ASN1_ENUMERATED *val = ASN1_ENUMERATED_new();
int res = 0;
if (val != NULL && ASN1_ENUMERATED_set(val, reason_code))
res = add1_extension(pexts, NID_crl_reason, 0 /* non-critical */, val);
ASN1_ENUMERATED_free(val);
return res;
}
OSSL_CMP_MSG *ossl_cmp_msg_create(OSSL_CMP_CTX *ctx, int bodytype)
{
OSSL_CMP_MSG *msg = NULL;
if (!ossl_assert(ctx != NULL))
return NULL;
if ((msg = OSSL_CMP_MSG_new(ctx->libctx, ctx->propq)) == NULL)
return NULL;
if (!ossl_cmp_hdr_init(ctx, msg->header)
|| !ossl_cmp_msg_set_bodytype(msg, bodytype))
goto err;
if (ctx->geninfo_ITAVs != NULL
&& !ossl_cmp_hdr_generalInfo_push1_items(msg->header,
ctx->geninfo_ITAVs))
goto err;
switch (bodytype) {
case OSSL_CMP_PKIBODY_IR:
case OSSL_CMP_PKIBODY_CR:
case OSSL_CMP_PKIBODY_KUR:
if ((msg->body->value.ir = OSSL_CRMF_MSGS_new()) == NULL)
goto err;
return msg;
case OSSL_CMP_PKIBODY_P10CR:
if (ctx->p10CSR == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_P10CSR);
goto err;
}
if ((msg->body->value.p10cr = X509_REQ_dup(ctx->p10CSR)) == NULL)
goto err;
return msg;
case OSSL_CMP_PKIBODY_IP:
case OSSL_CMP_PKIBODY_CP:
case OSSL_CMP_PKIBODY_KUP:
if ((msg->body->value.ip = OSSL_CMP_CERTREPMESSAGE_new()) == NULL)
goto err;
return msg;
case OSSL_CMP_PKIBODY_RR:
if ((msg->body->value.rr = sk_OSSL_CMP_REVDETAILS_new_null()) == NULL)
goto err;
return msg;
case OSSL_CMP_PKIBODY_RP:
if ((msg->body->value.rp = OSSL_CMP_REVREPCONTENT_new()) == NULL)
goto err;
return msg;
case OSSL_CMP_PKIBODY_CERTCONF:
if ((msg->body->value.certConf =
sk_OSSL_CMP_CERTSTATUS_new_null()) == NULL)
goto err;
return msg;
case OSSL_CMP_PKIBODY_PKICONF:
if ((msg->body->value.pkiconf = ASN1_TYPE_new()) == NULL)
goto err;
ASN1_TYPE_set(msg->body->value.pkiconf, V_ASN1_NULL, NULL);
return msg;
case OSSL_CMP_PKIBODY_POLLREQ:
if ((msg->body->value.pollReq = sk_OSSL_CMP_POLLREQ_new_null()) == NULL)
goto err;
return msg;
case OSSL_CMP_PKIBODY_POLLREP:
if ((msg->body->value.pollRep = sk_OSSL_CMP_POLLREP_new_null()) == NULL)
goto err;
return msg;
case OSSL_CMP_PKIBODY_GENM:
case OSSL_CMP_PKIBODY_GENP:
if ((msg->body->value.genm = sk_OSSL_CMP_ITAV_new_null()) == NULL)
goto err;
return msg;
case OSSL_CMP_PKIBODY_ERROR:
if ((msg->body->value.error = OSSL_CMP_ERRORMSGCONTENT_new()) == NULL)
goto err;
return msg;
default:
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
goto err;
}
err:
OSSL_CMP_MSG_free(msg);
return NULL;
}
#define HAS_SAN(ctx) \
(sk_GENERAL_NAME_num((ctx)->subjectAltNames) > 0 \
|| OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) == 1)
static const X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, int for_KUR,
const X509_NAME *ref_subj)
{
if (ctx->subjectName != NULL)
return IS_NULL_DN(ctx->subjectName) ? NULL : ctx->subjectName;
if (ctx->p10CSR != NULL) /* first default is from any given CSR */
return X509_REQ_get_subject_name(ctx->p10CSR);
if (for_KUR || !HAS_SAN(ctx))
/*
* For KUR, copy subject from any reference cert as fallback.
* For IR or CR, do the same only if there is no subjectAltName.
*/
return ref_subj;
return NULL;
}
OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
{
OSSL_CRMF_MSG *crm = NULL;
X509 *refcert = ctx->oldCert != NULL ? ctx->oldCert : ctx->cert;
/* refcert defaults to current client cert */
- EVP_PKEY *rkey = OSSL_CMP_CTX_get0_newPkey(ctx, 0);
+ EVP_PKEY *rkey = ossl_cmp_ctx_get0_newPubkey(ctx);
STACK_OF(GENERAL_NAME) *default_sans = NULL;
const X509_NAME *ref_subj =
refcert != NULL ? X509_get_subject_name(refcert) : NULL;
const X509_NAME *subject = determine_subj(ctx, for_KUR, ref_subj);
const X509_NAME *issuer = ctx->issuer != NULL || refcert == NULL
? (IS_NULL_DN(ctx->issuer) ? NULL : ctx->issuer)
: X509_get_issuer_name(refcert);
int crit = ctx->setSubjectAltNameCritical || subject == NULL;
/* RFC5280: subjectAltName MUST be critical if subject is null */
X509_EXTENSIONS *exts = NULL;
- if (rkey == NULL && ctx->p10CSR != NULL)
- rkey = X509_REQ_get0_pubkey(ctx->p10CSR);
- if (rkey == NULL && refcert != NULL)
- rkey = X509_get0_pubkey(refcert);
- if (rkey == NULL)
- rkey = ctx->pkey; /* default is independent of ctx->oldCert */
if (rkey == NULL) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PUBLIC_KEY);
return NULL;
#endif
}
if (for_KUR && refcert == NULL && ctx->p10CSR == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_REFERENCE_CERT);
return NULL;
}
if ((crm = OSSL_CRMF_MSG_new()) == NULL)
return NULL;
if (!OSSL_CRMF_MSG_set_certReqId(crm, rid)
/*
* fill certTemplate, corresponding to CertificationRequestInfo
* of PKCS#10. The rkey param cannot be NULL so far -
* it could be NULL if centralized key creation was supported
*/
|| !OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_MSG_get0_tmpl(crm), rkey,
subject, issuer, NULL /* serial */))
goto err;
if (ctx->days != 0) {
time_t now = time(NULL);
ASN1_TIME *notBefore = ASN1_TIME_adj(NULL, now, 0, 0);
ASN1_TIME *notAfter = ASN1_TIME_adj(NULL, now, ctx->days, 0);
if (notBefore == NULL
|| notAfter == NULL
|| !OSSL_CRMF_MSG_set0_validity(crm, notBefore, notAfter)) {
ASN1_TIME_free(notBefore);
ASN1_TIME_free(notAfter);
goto err;
}
}
/* extensions */
if (ctx->p10CSR != NULL
&& (exts = X509_REQ_get_extensions(ctx->p10CSR)) == NULL)
goto err;
if (!ctx->SubjectAltName_nodefault && !HAS_SAN(ctx) && refcert != NULL
&& (default_sans = X509V3_get_d2i(X509_get0_extensions(refcert),
NID_subject_alt_name, NULL, NULL))
!= NULL
&& !add1_extension(&exts, NID_subject_alt_name, crit, default_sans))
goto err;
if (ctx->reqExtensions != NULL /* augment/override existing ones */
&& !add_extensions(&exts, ctx->reqExtensions))
goto err;
if (sk_GENERAL_NAME_num(ctx->subjectAltNames) > 0
&& !add1_extension(&exts, NID_subject_alt_name,
crit, ctx->subjectAltNames))
goto err;
if (ctx->policies != NULL
&& !add1_extension(&exts, NID_certificate_policies,
ctx->setPoliciesCritical, ctx->policies))
goto err;
if (!OSSL_CRMF_MSG_set0_extensions(crm, exts))
goto err;
exts = NULL;
/* end fill certTemplate, now set any controls */
/* for KUR, set OldCertId according to D.6 */
if (for_KUR && refcert != NULL) {
OSSL_CRMF_CERTID *cid =
OSSL_CRMF_CERTID_gen(X509_get_issuer_name(refcert),
X509_get0_serialNumber(refcert));
int ret;
if (cid == NULL)
goto err;
ret = OSSL_CRMF_MSG_set1_regCtrl_oldCertID(crm, cid);
OSSL_CRMF_CERTID_free(cid);
if (ret == 0)
goto err;
}
goto end;
err:
OSSL_CRMF_MSG_free(crm);
crm = NULL;
end:
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
sk_GENERAL_NAME_pop_free(default_sans, GENERAL_NAME_free);
return crm;
}
OSSL_CMP_MSG *ossl_cmp_certreq_new(OSSL_CMP_CTX *ctx, int type,
const OSSL_CRMF_MSG *crm)
{
OSSL_CMP_MSG *msg;
OSSL_CRMF_MSG *local_crm = NULL;
if (!ossl_assert(ctx != NULL))
return NULL;
if (type != OSSL_CMP_PKIBODY_IR && type != OSSL_CMP_PKIBODY_CR
&& type != OSSL_CMP_PKIBODY_KUR && type != OSSL_CMP_PKIBODY_P10CR) {
ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
return NULL;
}
if (type == OSSL_CMP_PKIBODY_P10CR && crm != NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
return NULL;
}
if ((msg = ossl_cmp_msg_create(ctx, type)) == NULL)
goto err;
/* header */
if (ctx->implicitConfirm && !ossl_cmp_hdr_set_implicitConfirm(msg->header))
goto err;
/* body */
/* For P10CR the content has already been set in OSSL_CMP_MSG_create */
if (type != OSSL_CMP_PKIBODY_P10CR) {
EVP_PKEY *privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
- /*
- * privkey is NULL in case ctx->newPkey does not include a private key.
- * We then may try to use ctx->pkey as fallback/default, but only
- * if ctx-> newPkey does not include a (non-matching) public key:
- */
- if (privkey == NULL && OSSL_CMP_CTX_get0_newPkey(ctx, 0) == NULL)
- privkey = ctx->pkey; /* default is independent of ctx->oldCert */
- if (ctx->popoMethod == OSSL_CRMF_POPO_SIGNATURE && privkey == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY);
+ /* privkey is ctx->newPkey (if private, else NULL) or ctx->pkey */
+ if (ctx->popoMethod >= OSSL_CRMF_POPO_SIGNATURE && privkey == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY_FOR_POPO);
goto err;
}
if (crm == NULL) {
local_crm = OSSL_CMP_CTX_setup_CRM(ctx,
type == OSSL_CMP_PKIBODY_KUR,
OSSL_CMP_CERTREQID);
if (local_crm == NULL
|| !OSSL_CRMF_MSG_create_popo(ctx->popoMethod, local_crm,
privkey, ctx->digest,
ctx->libctx, ctx->propq))
goto err;
} else {
if ((local_crm = OSSL_CRMF_MSG_dup(crm)) == NULL)
goto err;
}
/* value.ir is same for cr and kur */
if (!sk_OSSL_CRMF_MSG_push(msg->body->value.ir, local_crm))
goto err;
local_crm = NULL;
}
if (!ossl_cmp_msg_protect(ctx, msg))
goto err;
return msg;
err:
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREQ);
OSSL_CRMF_MSG_free(local_crm);
OSSL_CMP_MSG_free(msg);
return NULL;
}
OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
int certReqId, const OSSL_CMP_PKISI *si,
X509 *cert, const X509 *encryption_recip,
STACK_OF(X509) *chain, STACK_OF(X509) *caPubs,
int unprotectedErrors)
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_CERTREPMESSAGE *repMsg = NULL;
OSSL_CMP_CERTRESPONSE *resp = NULL;
int status = OSSL_CMP_PKISTATUS_unspecified;
if (!ossl_assert(ctx != NULL && si != NULL))
return NULL;
if ((msg = ossl_cmp_msg_create(ctx, bodytype)) == NULL)
goto err;
repMsg = msg->body->value.ip; /* value.ip is same for cp and kup */
/* header */
if (ctx->implicitConfirm && !ossl_cmp_hdr_set_implicitConfirm(msg->header))
goto err;
/* body */
if ((resp = OSSL_CMP_CERTRESPONSE_new()) == NULL)
goto err;
OSSL_CMP_PKISI_free(resp->status);
if ((resp->status = OSSL_CMP_PKISI_dup(si)) == NULL
|| !ASN1_INTEGER_set(resp->certReqId, certReqId))
goto err;
status = ossl_cmp_pkisi_get_status(resp->status);
if (status != OSSL_CMP_PKISTATUS_rejection
&& status != OSSL_CMP_PKISTATUS_waiting && cert != NULL) {
if (encryption_recip != NULL) {
ERR_raise(ERR_LIB_CMP, ERR_R_UNSUPPORTED);
goto err;
}
if ((resp->certifiedKeyPair = OSSL_CMP_CERTIFIEDKEYPAIR_new())
== NULL)
goto err;
resp->certifiedKeyPair->certOrEncCert->type =
OSSL_CMP_CERTORENCCERT_CERTIFICATE;
if (!X509_up_ref(cert))
goto err;
resp->certifiedKeyPair->certOrEncCert->value.certificate = cert;
}
if (!sk_OSSL_CMP_CERTRESPONSE_push(repMsg->response, resp))
goto err;
resp = NULL;
if (bodytype == OSSL_CMP_PKIBODY_IP && caPubs != NULL
&& (repMsg->caPubs = X509_chain_up_ref(caPubs)) == NULL)
goto err;
if (sk_X509_num(chain) > 0
&& !ossl_x509_add_certs_new(&msg->extraCerts, chain,
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
goto err;
if (!unprotectedErrors
|| ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
if (!ossl_cmp_msg_protect(ctx, msg))
goto err;
return msg;
err:
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREP);
OSSL_CMP_CERTRESPONSE_free(resp);
OSSL_CMP_MSG_free(msg);
return NULL;
}
OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx)
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_REVDETAILS *rd;
int ret;
if (!ossl_assert(ctx != NULL && (ctx->oldCert != NULL
|| ctx->p10CSR != NULL)))
return NULL;
if ((rd = OSSL_CMP_REVDETAILS_new()) == NULL)
goto err;
/* Fill the template from the contents of the certificate to be revoked */
ret = ctx->oldCert != NULL
? OSSL_CRMF_CERTTEMPLATE_fill(rd->certDetails,
NULL /* pubkey would be redundant */,
NULL /* subject would be redundant */,
X509_get_issuer_name(ctx->oldCert),
X509_get0_serialNumber(ctx->oldCert))
: OSSL_CRMF_CERTTEMPLATE_fill(rd->certDetails,
X509_REQ_get0_pubkey(ctx->p10CSR),
X509_REQ_get_subject_name(ctx->p10CSR),
NULL, NULL);
if (!ret)
goto err;
/* revocation reason code is optional */
if (ctx->revocationReason != CRL_REASON_NONE
&& !add_crl_reason_extension(&rd->crlEntryDetails,
ctx->revocationReason))
goto err;
if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_RR)) == NULL)
goto err;
if (!sk_OSSL_CMP_REVDETAILS_push(msg->body->value.rr, rd))
goto err;
rd = NULL;
/* Revocation Passphrase according to section 5.3.19.9 could be set here */
if (!ossl_cmp_msg_protect(ctx, msg))
goto err;
return msg;
err:
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_RR);
OSSL_CMP_MSG_free(msg);
OSSL_CMP_REVDETAILS_free(rd);
return NULL;
}
OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
const OSSL_CRMF_CERTID *cid, int unprotectedErrors)
{
OSSL_CMP_REVREPCONTENT *rep = NULL;
OSSL_CMP_PKISI *si1 = NULL;
OSSL_CRMF_CERTID *cid_copy = NULL;
OSSL_CMP_MSG *msg = NULL;
if (!ossl_assert(ctx != NULL && si != NULL))
return NULL;
if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_RP)) == NULL)
goto err;
rep = msg->body->value.rp;
if ((si1 = OSSL_CMP_PKISI_dup(si)) == NULL)
goto err;
if (!sk_OSSL_CMP_PKISI_push(rep->status, si1)) {
OSSL_CMP_PKISI_free(si1);
goto err;
}
if ((rep->revCerts = sk_OSSL_CRMF_CERTID_new_null()) == NULL)
goto err;
if (cid != NULL) {
if ((cid_copy = OSSL_CRMF_CERTID_dup(cid)) == NULL)
goto err;
if (!sk_OSSL_CRMF_CERTID_push(rep->revCerts, cid_copy)) {
OSSL_CRMF_CERTID_free(cid_copy);
goto err;
}
}
if (!unprotectedErrors
|| ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
if (!ossl_cmp_msg_protect(ctx, msg))
goto err;
return msg;
err:
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_RP);
OSSL_CMP_MSG_free(msg);
return NULL;
}
OSSL_CMP_MSG *ossl_cmp_pkiconf_new(OSSL_CMP_CTX *ctx)
{
OSSL_CMP_MSG *msg;
if (!ossl_assert(ctx != NULL))
return NULL;
if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_PKICONF)) == NULL)
goto err;
if (ossl_cmp_msg_protect(ctx, msg))
return msg;
err:
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_PKICONF);
OSSL_CMP_MSG_free(msg);
return NULL;
}
int ossl_cmp_msg_gen_push0_ITAV(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav)
{
int bodytype;
if (!ossl_assert(msg != NULL && itav != NULL))
return 0;
bodytype = OSSL_CMP_MSG_get_bodytype(msg);
if (bodytype != OSSL_CMP_PKIBODY_GENM
&& bodytype != OSSL_CMP_PKIBODY_GENP) {
ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS);
return 0;
}
/* value.genp has the same structure, so this works for genp as well */
return OSSL_CMP_ITAV_push0_stack_item(&msg->body->value.genm, itav);
}
int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
const STACK_OF(OSSL_CMP_ITAV) *itavs)
{
int i;
OSSL_CMP_ITAV *itav = NULL;
if (!ossl_assert(msg != NULL))
return 0;
for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) {
itav = OSSL_CMP_ITAV_dup(sk_OSSL_CMP_ITAV_value(itavs, i));
if (itav == NULL
|| !ossl_cmp_msg_gen_push0_ITAV(msg, itav)) {
OSSL_CMP_ITAV_free(itav);
return 0;
}
}
return 1;
}
/*
* Creates a new General Message/Response with an empty itav stack
* returns a pointer to the PKIMessage on success, NULL on error
*/
static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx,
const STACK_OF(OSSL_CMP_ITAV) *itavs,
int body_type, int err_code)
{
OSSL_CMP_MSG *msg = NULL;
if (!ossl_assert(ctx != NULL))
return NULL;
if ((msg = ossl_cmp_msg_create(ctx, body_type)) == NULL)
return NULL;
if (itavs != NULL && !ossl_cmp_msg_gen_push1_ITAVs(msg, itavs))
goto err;
if (!ossl_cmp_msg_protect(ctx, msg))
goto err;
return msg;
err:
ERR_raise(ERR_LIB_CMP, err_code);
OSSL_CMP_MSG_free(msg);
return NULL;
}
OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx)
{
return gen_new(ctx, ctx->genm_ITAVs,
OSSL_CMP_PKIBODY_GENM, CMP_R_ERROR_CREATING_GENM);
}
OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx,
const STACK_OF(OSSL_CMP_ITAV) *itavs)
{
return gen_new(ctx, itavs,
OSSL_CMP_PKIBODY_GENP, CMP_R_ERROR_CREATING_GENP);
}
OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
int64_t errorCode, const char *details,
int unprotected)
{
OSSL_CMP_MSG *msg = NULL;
const char *lib = NULL, *reason = NULL;
OSSL_CMP_PKIFREETEXT *ft;
if (!ossl_assert(ctx != NULL && si != NULL))
return NULL;
if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_ERROR)) == NULL)
goto err;
OSSL_CMP_PKISI_free(msg->body->value.error->pKIStatusInfo);
if ((msg->body->value.error->pKIStatusInfo = OSSL_CMP_PKISI_dup(si))
== NULL)
goto err;
if ((msg->body->value.error->errorCode = ASN1_INTEGER_new()) == NULL)
goto err;
if (!ASN1_INTEGER_set_int64(msg->body->value.error->errorCode, errorCode))
goto err;
if (errorCode > 0
&& (uint64_t)errorCode < ((uint64_t)ERR_SYSTEM_FLAG << 1)) {
lib = ERR_lib_error_string((unsigned long)errorCode);
reason = ERR_reason_error_string((unsigned long)errorCode);
}
if (lib != NULL || reason != NULL || details != NULL) {
if ((ft = sk_ASN1_UTF8STRING_new_null()) == NULL)
goto err;
msg->body->value.error->errorDetails = ft;
if (lib != NULL && *lib != '\0'
&& !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, lib, -1))
goto err;
if (reason != NULL && *reason != '\0'
&& !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, reason, -1))
goto err;
if (details != NULL
&& !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, details, -1))
goto err;
}
if (!unprotected && !ossl_cmp_msg_protect(ctx, msg))
goto err;
return msg;
err:
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_ERROR);
OSSL_CMP_MSG_free(msg);
return NULL;
}
/*
* Set the certHash field of a OSSL_CMP_CERTSTATUS structure.
* This is used in the certConf message, for example,
* to confirm that the certificate was received successfully.
*/
int ossl_cmp_certstatus_set0_certHash(OSSL_CMP_CERTSTATUS *certStatus,
ASN1_OCTET_STRING *hash)
{
if (!ossl_assert(certStatus != NULL))
return 0;
ASN1_OCTET_STRING_free(certStatus->certHash);
certStatus->certHash = hash;
return 1;
}
-OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
- const char *text)
+OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int certReqId,
+ int fail_info, const char *text)
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_CERTSTATUS *certStatus = NULL;
ASN1_OCTET_STRING *certHash = NULL;
OSSL_CMP_PKISI *sinfo;
- if (!ossl_assert(ctx != NULL && ctx->newCert != NULL))
+ if (!ossl_assert(ctx != NULL && ctx->newCert != NULL
+ && (certReqId == OSSL_CMP_CERTREQID
+ || certReqId == OSSL_CMP_CERTREQID_NONE)))
return NULL;
if ((unsigned)fail_info > OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN) {
ERR_raise(ERR_LIB_CMP, CMP_R_FAIL_INFO_OUT_OF_RANGE);
return NULL;
}
if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_CERTCONF)) == NULL)
goto err;
if ((certStatus = OSSL_CMP_CERTSTATUS_new()) == NULL)
goto err;
/* consume certStatus into msg right away so it gets deallocated with msg */
- if (!sk_OSSL_CMP_CERTSTATUS_push(msg->body->value.certConf, certStatus))
+ if (sk_OSSL_CMP_CERTSTATUS_push(msg->body->value.certConf, certStatus) < 1) {
+ OSSL_CMP_CERTSTATUS_free(certStatus);
goto err;
+ }
+
/* set the ID of the certReq */
- if (!ASN1_INTEGER_set(certStatus->certReqId, OSSL_CMP_CERTREQID))
+ if (!ASN1_INTEGER_set(certStatus->certReqId, certReqId))
goto err;
/*
* The hash of the certificate, using the same hash algorithm
* as is used to create and verify the certificate signature.
* If not available, a default hash algorithm is used.
*/
if ((certHash = X509_digest_sig(ctx->newCert, NULL, NULL)) == NULL)
goto err;
if (!ossl_cmp_certstatus_set0_certHash(certStatus, certHash))
goto err;
certHash = NULL;
/*
* For any particular CertStatus, omission of the statusInfo field
* indicates ACCEPTANCE of the specified certificate. Alternatively,
* explicit status details (with respect to acceptance or rejection) MAY
* be provided in the statusInfo field, perhaps for auditing purposes at
* the CA/RA.
*/
sinfo = fail_info != 0 ?
OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection, fail_info, text) :
OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_accepted, 0, text);
if (sinfo == NULL)
goto err;
certStatus->statusInfo = sinfo;
if (!ossl_cmp_msg_protect(ctx, msg))
goto err;
return msg;
err:
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTCONF);
OSSL_CMP_MSG_free(msg);
ASN1_OCTET_STRING_free(certHash);
return NULL;
}
OSSL_CMP_MSG *ossl_cmp_pollReq_new(OSSL_CMP_CTX *ctx, int crid)
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_POLLREQ *preq = NULL;
if (!ossl_assert(ctx != NULL))
return NULL;
if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_POLLREQ)) == NULL)
goto err;
if ((preq = OSSL_CMP_POLLREQ_new()) == NULL
|| !ASN1_INTEGER_set(preq->certReqId, crid)
|| !sk_OSSL_CMP_POLLREQ_push(msg->body->value.pollReq, preq))
goto err;
preq = NULL;
if (!ossl_cmp_msg_protect(ctx, msg))
goto err;
return msg;
err:
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREQ);
OSSL_CMP_POLLREQ_free(preq);
OSSL_CMP_MSG_free(msg);
return NULL;
}
OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
int64_t poll_after)
{
OSSL_CMP_MSG *msg;
OSSL_CMP_POLLREP *prep;
if (!ossl_assert(ctx != NULL))
return NULL;
if ((msg = ossl_cmp_msg_create(ctx, OSSL_CMP_PKIBODY_POLLREP)) == NULL)
goto err;
if ((prep = OSSL_CMP_POLLREP_new()) == NULL)
goto err;
if (!sk_OSSL_CMP_POLLREP_push(msg->body->value.pollRep, prep))
goto err;
if (!ASN1_INTEGER_set(prep->certReqId, crid))
goto err;
if (!ASN1_INTEGER_set_int64(prep->checkAfter, poll_after))
goto err;
if (!ossl_cmp_msg_protect(ctx, msg))
goto err;
return msg;
err:
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREP);
OSSL_CMP_MSG_free(msg);
return NULL;
}
/*-
* returns the status field of the RevRepContent with the given
* request/sequence id inside a revocation response.
* RevRepContent has the revocation statuses in same order as they were sent in
* RevReqContent.
* returns NULL on error
*/
OSSL_CMP_PKISI *
ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
{
OSSL_CMP_PKISI *status;
if (!ossl_assert(rrep != NULL))
return NULL;
if ((status = sk_OSSL_CMP_PKISI_value(rrep->status, rsid)) != NULL)
return status;
ERR_raise(ERR_LIB_CMP, CMP_R_PKISTATUSINFO_NOT_FOUND);
return NULL;
}
/*
* returns the CertId field in the revCerts part of the RevRepContent
* with the given request/sequence id inside a revocation response.
* RevRepContent has the CertIds in same order as they were sent in
* RevReqContent.
* returns NULL on error
*/
OSSL_CRMF_CERTID *
ossl_cmp_revrepcontent_get_CertId(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
{
OSSL_CRMF_CERTID *cid = NULL;
if (!ossl_assert(rrep != NULL))
return NULL;
if ((cid = sk_OSSL_CRMF_CERTID_value(rrep->revCerts, rsid)) != NULL)
return cid;
ERR_raise(ERR_LIB_CMP, CMP_R_CERTID_NOT_FOUND);
return NULL;
}
static int suitable_rid(const ASN1_INTEGER *certReqId, int rid)
{
int trid;
- if (rid == -1)
+ if (rid == OSSL_CMP_CERTREQID_NONE)
return 1;
trid = ossl_cmp_asn1_get_int(certReqId);
- if (trid == -1) {
+ if (trid == OSSL_CMP_CERTREQID_NONE) {
ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
return 0;
}
return rid == trid;
}
/*
* returns a pointer to the PollResponse with the given CertReqId
* (or the first one in case -1) inside a PollRepContent
* returns NULL on error or if no suitable PollResponse available
*/
OSSL_CMP_POLLREP *
ossl_cmp_pollrepcontent_get0_pollrep(const OSSL_CMP_POLLREPCONTENT *prc,
int rid)
{
OSSL_CMP_POLLREP *pollRep = NULL;
int i;
if (!ossl_assert(prc != NULL))
return NULL;
for (i = 0; i < sk_OSSL_CMP_POLLREP_num(prc); i++) {
pollRep = sk_OSSL_CMP_POLLREP_value(prc, i);
if (suitable_rid(pollRep->certReqId, rid))
return pollRep;
}
ERR_raise_data(ERR_LIB_CMP, CMP_R_CERTRESPONSE_NOT_FOUND,
"expected certReqId = %d", rid);
return NULL;
}
/*
* returns a pointer to the CertResponse with the given CertReqId
* (or the first one in case -1) inside a CertRepMessage
* returns NULL on error or if no suitable CertResponse available
*/
OSSL_CMP_CERTRESPONSE *
ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
int rid)
{
OSSL_CMP_CERTRESPONSE *crep = NULL;
int i;
if (!ossl_assert(crm != NULL && crm->response != NULL))
return NULL;
for (i = 0; i < sk_OSSL_CMP_CERTRESPONSE_num(crm->response); i++) {
crep = sk_OSSL_CMP_CERTRESPONSE_value(crm->response, i);
if (suitable_rid(crep->certReqId, rid))
return crep;
}
ERR_raise_data(ERR_LIB_CMP, CMP_R_CERTRESPONSE_NOT_FOUND,
"expected certReqId = %d", rid);
return NULL;
}
/*-
* Retrieve the newly enrolled certificate from the given certResponse crep.
- * In case of indirect POPO uses the libctx and propq from ctx and private key.
+ * Uses libctx and propq from ctx, in case of indirect POPO also private key.
* Returns a pointer to a copy of the found certificate, or NULL if not found.
*/
-X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CERTRESPONSE *crep,
- const OSSL_CMP_CTX *ctx, EVP_PKEY *pkey)
+X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_CERTRESPONSE *crep)
{
OSSL_CMP_CERTORENCCERT *coec;
X509 *crt = NULL;
+ EVP_PKEY *pkey;
if (!ossl_assert(crep != NULL && ctx != NULL))
return NULL;
if (crep->certifiedKeyPair
&& (coec = crep->certifiedKeyPair->certOrEncCert) != NULL) {
switch (coec->type) {
case OSSL_CMP_CERTORENCCERT_CERTIFICATE:
crt = X509_dup(coec->value.certificate);
break;
case OSSL_CMP_CERTORENCCERT_ENCRYPTEDCERT:
/* cert encrypted for indirect PoP; RFC 4210, 5.2.8.2 */
+ pkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
+ /* pkey is ctx->newPkey (if private, else NULL) or ctx->pkey */
if (pkey == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY);
return NULL;
}
crt =
OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(coec->value.encryptedCert,
ctx->libctx, ctx->propq,
pkey);
break;
default:
ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_CERT_TYPE);
return NULL;
}
}
if (crt == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND);
else
(void)ossl_x509_set0_libctx(crt, ctx->libctx, ctx->propq);
return crt;
}
int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
{
if (ctx == NULL || msg == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (!ossl_cmp_hdr_set_transactionID(ctx, msg->header))
return 0;
return msg->header->protectionAlg == NULL
|| ossl_cmp_msg_protect(ctx, msg);
}
+int OSSL_CMP_MSG_update_recipNonce(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
+{
+ if (ctx == NULL || msg == NULL || msg->header == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (ctx->recipNonce == NULL) /* nothing to do for 1st msg in transaction */
+ return 1;
+ if (!ossl_cmp_asn1_octet_string_set1(&msg->header->recipNonce,
+ ctx->recipNonce))
+ return 0;
+ return msg->header->protectionAlg == NULL || ossl_cmp_msg_protect(ctx, msg);
+}
+
OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file, OSSL_LIB_CTX *libctx,
const char *propq)
{
OSSL_CMP_MSG *msg;
BIO *bio = NULL;
if (file == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
msg = OSSL_CMP_MSG_new(libctx, propq);
if (msg == NULL){
ERR_raise(ERR_LIB_CMP, ERR_R_MALLOC_FAILURE);
return NULL;
}
if ((bio = BIO_new_file(file, "rb")) == NULL
|| d2i_OSSL_CMP_MSG_bio(bio, &msg) == NULL) {
OSSL_CMP_MSG_free(msg);
msg = NULL;
}
BIO_free(bio);
return msg;
}
int OSSL_CMP_MSG_write(const char *file, const OSSL_CMP_MSG *msg)
{
BIO *bio;
int res;
if (file == NULL || msg == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return -1;
}
bio = BIO_new_file(file, "wb");
if (bio == NULL)
return -2;
res = i2d_OSSL_CMP_MSG_bio(bio, msg);
BIO_free(bio);
return res;
}
OSSL_CMP_MSG *d2i_OSSL_CMP_MSG(OSSL_CMP_MSG **msg, const unsigned char **in,
long len)
{
OSSL_LIB_CTX *libctx = NULL;
const char *propq = NULL;
if (msg != NULL && *msg != NULL) {
libctx = (*msg)->libctx;
propq = (*msg)->propq;
}
return (OSSL_CMP_MSG *)ASN1_item_d2i_ex((ASN1_VALUE **)msg, in, len,
ASN1_ITEM_rptr(OSSL_CMP_MSG),
libctx, propq);
}
int i2d_OSSL_CMP_MSG(const OSSL_CMP_MSG *msg, unsigned char **out)
{
return ASN1_item_i2d((const ASN1_VALUE *)msg, out,
ASN1_ITEM_rptr(OSSL_CMP_MSG));
}
OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg)
{
OSSL_LIB_CTX *libctx = NULL;
const char *propq = NULL;
if (msg != NULL && *msg != NULL) {
libctx = (*msg)->libctx;
propq = (*msg)->propq;
}
return ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(OSSL_CMP_MSG), bio, msg, libctx,
propq);
}
int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg)
{
return ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bio, msg);
}
diff --git a/crypto/cmp/cmp_protect.c b/crypto/cmp/cmp_protect.c
index 02526196ad2a..539f6534cd01 100644
--- a/crypto/cmp/cmp_protect.c
+++ b/crypto/cmp/cmp_protect.c
@@ -1,332 +1,334 @@
/*
- * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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"
/* explicit #includes not strictly needed since implied by the above: */
#include <openssl/asn1t.h>
#include <openssl/cmp.h>
#include <openssl/crmf.h>
#include <openssl/err.h>
#include <openssl/x509.h>
/*
* This function is also used by the internal verify_PBMAC() in cmp_vfy.c.
*
* Calculate protection for given PKImessage according to
* the algorithm and parameters in the message header's protectionAlg
* using the credentials, library context, and property criteria in the ctx.
*
* returns ASN1_BIT_STRING representing the protection on success, else NULL
*/
ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *msg)
{
ASN1_BIT_STRING *prot = NULL;
OSSL_CMP_PROTECTEDPART prot_part;
const ASN1_OBJECT *algorOID = NULL;
const void *ppval = NULL;
int pptype = 0;
if (!ossl_assert(ctx != NULL && msg != NULL))
return NULL;
/* construct data to be signed */
prot_part.header = msg->header;
prot_part.body = msg->body;
if (msg->header->protectionAlg == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_ALGORITHM_ID);
return NULL;
}
X509_ALGOR_get0(&algorOID, &pptype, &ppval, msg->header->protectionAlg);
if (OBJ_obj2nid(algorOID) == NID_id_PasswordBasedMAC) {
int len;
size_t prot_part_der_len;
unsigned char *prot_part_der = NULL;
size_t sig_len;
unsigned char *protection = NULL;
OSSL_CRMF_PBMPARAMETER *pbm = NULL;
ASN1_STRING *pbm_str = NULL;
const unsigned char *pbm_str_uc = NULL;
if (ctx->secretValue == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PBM_SECRET);
return NULL;
}
if (ppval == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CALCULATING_PROTECTION);
return NULL;
}
len = i2d_OSSL_CMP_PROTECTEDPART(&prot_part, &prot_part_der);
if (len < 0 || prot_part_der == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CALCULATING_PROTECTION);
goto end;
}
prot_part_der_len = (size_t)len;
pbm_str = (ASN1_STRING *)ppval;
pbm_str_uc = pbm_str->data;
pbm = d2i_OSSL_CRMF_PBMPARAMETER(NULL, &pbm_str_uc, pbm_str->length);
if (pbm == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_ALGORITHM_OID);
goto end;
}
if (!OSSL_CRMF_pbm_new(ctx->libctx, ctx->propq,
pbm, prot_part_der, prot_part_der_len,
ctx->secretValue->data, ctx->secretValue->length,
&protection, &sig_len))
goto end;
if ((prot = ASN1_BIT_STRING_new()) == NULL)
goto end;
/* OpenSSL defaults all bit strings to be encoded as ASN.1 NamedBitList */
prot->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
prot->flags |= ASN1_STRING_FLAG_BITS_LEFT;
if (!ASN1_BIT_STRING_set(prot, protection, sig_len)) {
ASN1_BIT_STRING_free(prot);
prot = NULL;
}
end:
OSSL_CRMF_PBMPARAMETER_free(pbm);
OPENSSL_free(protection);
OPENSSL_free(prot_part_der);
return prot;
} else {
int md_nid;
const EVP_MD *md = NULL;
if (ctx->pkey == NULL) {
ERR_raise(ERR_LIB_CMP,
CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION);
return NULL;
}
if (!OBJ_find_sigid_algs(OBJ_obj2nid(algorOID), &md_nid, NULL)
|| (md = EVP_get_digestbynid(md_nid)) == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_ALGORITHM_ID);
return NULL;
}
if ((prot = ASN1_BIT_STRING_new()) == NULL)
return NULL;
if (ASN1_item_sign_ex(ASN1_ITEM_rptr(OSSL_CMP_PROTECTEDPART), NULL,
NULL, prot, &prot_part, NULL, ctx->pkey, md,
ctx->libctx, ctx->propq))
return prot;
ASN1_BIT_STRING_free(prot);
return NULL;
}
}
+/* ctx is not const just because ctx->chain may get adapted */
int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
{
if (!ossl_assert(ctx != NULL && msg != NULL))
return 0;
/* Add first ctx->cert and its chain if using signature-based protection */
if (!ctx->unprotectedSend && ctx->secretValue == NULL
&& ctx->cert != NULL && ctx->pkey != NULL) {
int prepend = X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
| X509_ADD_FLAG_PREPEND | X509_ADD_FLAG_NO_SS;
/* if not yet done try to build chain using available untrusted certs */
if (ctx->chain == NULL) {
ossl_cmp_debug(ctx,
"trying to build chain for own CMP signer cert");
ctx->chain = X509_build_chain(ctx->cert, ctx->untrusted, NULL, 0,
ctx->libctx, ctx->propq);
if (ctx->chain != NULL) {
ossl_cmp_debug(ctx,
"success building chain for own CMP signer cert");
} else {
/* dump errors to avoid confusion when printing further ones */
OSSL_CMP_CTX_print_errors(ctx);
ossl_cmp_warn(ctx,
"could not build chain for own CMP signer cert");
}
}
if (ctx->chain != NULL) {
if (!ossl_x509_add_certs_new(&msg->extraCerts, ctx->chain, prepend))
return 0;
} else {
/* make sure that at least our own signer cert is included first */
if (!ossl_x509_add_cert_new(&msg->extraCerts, ctx->cert, prepend))
return 0;
ossl_cmp_debug(ctx, "fallback: adding just own CMP signer cert");
}
}
/* add any additional certificates from ctx->extraCertsOut */
if (!ossl_x509_add_certs_new(&msg->extraCerts, ctx->extraCertsOut,
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
return 0;
/* in case extraCerts are empty list avoid empty ASN.1 sequence */
if (sk_X509_num(msg->extraCerts) == 0) {
sk_X509_free(msg->extraCerts);
msg->extraCerts = NULL;
}
return 1;
}
/*
* Create an X509_ALGOR structure for PasswordBasedMAC protection based on
* the pbm settings in the context
*/
static int set_pbmac_algor(const OSSL_CMP_CTX *ctx, X509_ALGOR **alg)
{
OSSL_CRMF_PBMPARAMETER *pbm = NULL;
unsigned char *pbm_der = NULL;
int pbm_der_len;
ASN1_STRING *pbm_str = NULL;
if (!ossl_assert(ctx != NULL))
return 0;
pbm = OSSL_CRMF_pbmp_new(ctx->libctx, ctx->pbm_slen,
EVP_MD_get_type(ctx->pbm_owf), ctx->pbm_itercnt,
ctx->pbm_mac);
pbm_str = ASN1_STRING_new();
if (pbm == NULL || pbm_str == NULL)
goto err;
if ((pbm_der_len = i2d_OSSL_CRMF_PBMPARAMETER(pbm, &pbm_der)) < 0)
goto err;
if (!ASN1_STRING_set(pbm_str, pbm_der, pbm_der_len))
goto err;
if (*alg == NULL && (*alg = X509_ALGOR_new()) == NULL)
goto err;
OPENSSL_free(pbm_der);
X509_ALGOR_set0(*alg, OBJ_nid2obj(NID_id_PasswordBasedMAC),
V_ASN1_SEQUENCE, pbm_str);
OSSL_CRMF_PBMPARAMETER_free(pbm);
return 1;
err:
ASN1_STRING_free(pbm_str);
OPENSSL_free(pbm_der);
OSSL_CRMF_PBMPARAMETER_free(pbm);
return 0;
}
static int set_sig_algor(const OSSL_CMP_CTX *ctx, X509_ALGOR **alg)
{
int nid = 0;
ASN1_OBJECT *algo = NULL;
if (!OBJ_find_sigid_by_algs(&nid, EVP_MD_get_type(ctx->digest),
EVP_PKEY_get_id(ctx->pkey))) {
ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_KEY_TYPE);
return 0;
}
if ((algo = OBJ_nid2obj(nid)) == NULL)
return 0;
if (*alg == NULL && (*alg = X509_ALGOR_new()) == NULL)
return 0;
if (X509_ALGOR_set0(*alg, algo, V_ASN1_UNDEF, NULL))
return 1;
ASN1_OBJECT_free(algo);
return 0;
}
static int set_senderKID(const OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg,
const ASN1_OCTET_STRING *id)
{
if (id == NULL)
id = ctx->referenceValue; /* standard for PBM, fallback for sig-based */
return id == NULL || ossl_cmp_hdr_set1_senderKID(msg->header, id);
}
+/* ctx is not const just because ctx->chain may get adapted */
int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
{
if (!ossl_assert(ctx != NULL && msg != NULL))
return 0;
/*
* For the case of re-protection remove pre-existing protection.
*/
X509_ALGOR_free(msg->header->protectionAlg);
msg->header->protectionAlg = NULL;
ASN1_BIT_STRING_free(msg->protection);
msg->protection = NULL;
if (ctx->unprotectedSend) {
if (!set_senderKID(ctx, msg, NULL))
goto err;
} else if (ctx->secretValue != NULL) {
/* use PasswordBasedMac according to 5.1.3.1 if secretValue is given */
if (!set_pbmac_algor(ctx, &msg->header->protectionAlg))
goto err;
if (!set_senderKID(ctx, msg, NULL))
goto err;
/*
* will add any additional certificates from ctx->extraCertsOut
* while not needed to validate the protection certificate,
* the option to do this might be handy for certain use cases
*/
} else if (ctx->cert != NULL && ctx->pkey != NULL) {
/* use MSG_SIG_ALG according to 5.1.3.3 if client cert and key given */
/* make sure that key and certificate match */
if (!X509_check_private_key(ctx->cert, ctx->pkey)) {
ERR_raise(ERR_LIB_CMP, CMP_R_CERT_AND_KEY_DO_NOT_MATCH);
goto err;
}
if (!set_sig_algor(ctx, &msg->header->protectionAlg))
goto err;
/* set senderKID to keyIdentifier of the cert according to 5.1.1 */
if (!set_senderKID(ctx, msg, X509_get0_subject_key_id(ctx->cert)))
goto err;
/*
* will add ctx->cert followed, if possible, by its chain built
* from ctx->untrusted, and then ctx->extraCertsOut
*/
} else {
ERR_raise(ERR_LIB_CMP,
CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION);
goto err;
}
if (!ctx->unprotectedSend
&& ((msg->protection = ossl_cmp_calc_protection(ctx, msg)) == NULL))
goto err;
/*
* For signature-based protection add ctx->cert followed by its chain.
* Finally add any additional certificates from ctx->extraCertsOut;
* even if not needed to validate the protection
* the option to do this might be handy for certain use cases.
*/
if (!ossl_cmp_msg_add_extraCerts(ctx, msg))
goto err;
/*
* As required by RFC 4210 section 5.1.1., if the sender name is not known
* to the client it set to NULL-DN. In this case for identification at least
* the senderKID must be set, where we took the referenceValue as fallback.
*/
if (!(ossl_cmp_general_name_is_NULL_DN(msg->header->sender)
&& msg->header->senderKID == NULL))
return 1;
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_SENDER_IDENTIFICATION);
err:
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROTECTING_MESSAGE);
return 0;
}
diff --git a/crypto/cmp/cmp_server.c b/crypto/cmp/cmp_server.c
index 946c32c45ebf..96f977636ca2 100644
--- a/crypto/cmp/cmp_server.c
+++ b/crypto/cmp/cmp_server.c
@@ -1,644 +1,665 @@
/*
- * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/* general CMP server functions */
#include <openssl/asn1t.h>
#include "cmp_local.h"
/* explicit #includes not strictly needed since implied by the above: */
#include <openssl/cmp.h>
#include <openssl/err.h>
/* the context for the generic CMP server */
struct ossl_cmp_srv_ctx_st
{
- OSSL_CMP_CTX *ctx; /* Client CMP context, partly reused for srv */
- void *custom_ctx; /* pointer to specific server context */
+ void *custom_ctx; /* pointer to application-specific server context */
+ OSSL_CMP_CTX *ctx; /* Client CMP context, reusing transactionID etc. */
+ int certReqId; /* id of last ir/cr/kur, OSSL_CMP_CERTREQID_NONE for p10cr */
OSSL_CMP_SRV_cert_request_cb_t process_cert_request;
OSSL_CMP_SRV_rr_cb_t process_rr;
OSSL_CMP_SRV_genm_cb_t process_genm;
OSSL_CMP_SRV_error_cb_t process_error;
OSSL_CMP_SRV_certConf_cb_t process_certConf;
OSSL_CMP_SRV_pollReq_cb_t process_pollReq;
int sendUnprotectedErrors; /* Send error and rejection msgs unprotected */
int acceptUnprotected; /* Accept requests with no/invalid prot. */
int acceptRAVerified; /* Accept ir/cr/kur with POPO RAVerified */
int grantImplicitConfirm; /* Grant implicit confirmation if requested */
}; /* OSSL_CMP_SRV_CTX */
void OSSL_CMP_SRV_CTX_free(OSSL_CMP_SRV_CTX *srv_ctx)
{
if (srv_ctx == NULL)
return;
OSSL_CMP_CTX_free(srv_ctx->ctx);
OPENSSL_free(srv_ctx);
}
OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(OSSL_LIB_CTX *libctx, const char *propq)
{
OSSL_CMP_SRV_CTX *ctx = OPENSSL_zalloc(sizeof(OSSL_CMP_SRV_CTX));
if (ctx == NULL)
goto err;
if ((ctx->ctx = OSSL_CMP_CTX_new(libctx, propq)) == NULL)
goto err;
+ ctx->certReqId = OSSL_CMP_CERTREQID_INVALID;
/* all other elements are initialized to 0 or NULL, respectively */
return ctx;
err:
OSSL_CMP_SRV_CTX_free(ctx);
return NULL;
}
int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
OSSL_CMP_SRV_cert_request_cb_t process_cert_request,
OSSL_CMP_SRV_rr_cb_t process_rr,
OSSL_CMP_SRV_genm_cb_t process_genm,
OSSL_CMP_SRV_error_cb_t process_error,
OSSL_CMP_SRV_certConf_cb_t process_certConf,
OSSL_CMP_SRV_pollReq_cb_t process_pollReq)
{
if (srv_ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->custom_ctx = custom_ctx;
srv_ctx->process_cert_request = process_cert_request;
srv_ctx->process_rr = process_rr;
srv_ctx->process_genm = process_genm;
srv_ctx->process_error = process_error;
srv_ctx->process_certConf = process_certConf;
srv_ctx->process_pollReq = process_pollReq;
return 1;
}
OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx)
{
if (srv_ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return srv_ctx->ctx;
}
void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx)
{
if (srv_ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
return srv_ctx->custom_ctx;
}
int OSSL_CMP_SRV_CTX_set_send_unprotected_errors(OSSL_CMP_SRV_CTX *srv_ctx,
int val)
{
if (srv_ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->sendUnprotectedErrors = val != 0;
return 1;
}
int OSSL_CMP_SRV_CTX_set_accept_unprotected(OSSL_CMP_SRV_CTX *srv_ctx, int val)
{
if (srv_ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->acceptUnprotected = val != 0;
return 1;
}
int OSSL_CMP_SRV_CTX_set_accept_raverified(OSSL_CMP_SRV_CTX *srv_ctx, int val)
{
if (srv_ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->acceptRAVerified = val != 0;
return 1;
}
int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx,
int val)
{
if (srv_ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->grantImplicitConfirm = val != 0;
return 1;
}
/*
* Processes an ir/cr/p10cr/kur and returns a certification response.
* Only handles the first certification request contained in req
* returns an ip/cp/kup on success and NULL on error
*/
static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_PKISI *si = NULL;
X509 *certOut = NULL;
STACK_OF(X509) *chainOut = NULL, *caPubs = NULL;
const OSSL_CRMF_MSG *crm = NULL;
const X509_REQ *p10cr = NULL;
int bodytype;
int certReqId;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
switch (OSSL_CMP_MSG_get_bodytype(req)) {
case OSSL_CMP_PKIBODY_P10CR:
case OSSL_CMP_PKIBODY_CR:
bodytype = OSSL_CMP_PKIBODY_CP;
break;
case OSSL_CMP_PKIBODY_IR:
bodytype = OSSL_CMP_PKIBODY_IP;
break;
case OSSL_CMP_PKIBODY_KUR:
bodytype = OSSL_CMP_PKIBODY_KUP;
break;
default:
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
return NULL;
}
if (OSSL_CMP_MSG_get_bodytype(req) == OSSL_CMP_PKIBODY_P10CR) {
- certReqId = OSSL_CMP_CERTREQID;
+ certReqId = OSSL_CMP_CERTREQID_NONE; /* p10cr does not include an Id */
p10cr = req->body->value.p10cr;
} else {
OSSL_CRMF_MSGS *reqs = req->body->value.ir; /* same for cr and kur */
if (sk_OSSL_CRMF_MSG_num(reqs) != 1) {
ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
if ((crm = sk_OSSL_CRMF_MSG_value(reqs, OSSL_CMP_CERTREQID)) == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_CERTREQMSG_NOT_FOUND);
return NULL;
}
certReqId = OSSL_CRMF_MSG_get_certReqId(crm);
+ if (certReqId != OSSL_CMP_CERTREQID) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+ return 0;
+ }
}
+ srv_ctx->certReqId = certReqId;
if (!ossl_cmp_verify_popo(srv_ctx->ctx, req, srv_ctx->acceptRAVerified)) {
/* Proof of possession could not be verified */
si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection,
1 << OSSL_CMP_PKIFAILUREINFO_badPOP,
ERR_reason_error_string(ERR_peek_error()));
if (si == NULL)
return NULL;
} else {
OSSL_CMP_PKIHEADER *hdr = OSSL_CMP_MSG_get0_header(req);
si = srv_ctx->process_cert_request(srv_ctx, req, certReqId, crm, p10cr,
&certOut, &chainOut, &caPubs);
if (si == NULL)
goto err;
/* set OSSL_CMP_OPT_IMPLICIT_CONFIRM if and only if transaction ends */
if (!OSSL_CMP_CTX_set_option(srv_ctx->ctx,
OSSL_CMP_OPT_IMPLICIT_CONFIRM,
ossl_cmp_hdr_has_implicitConfirm(hdr)
&& srv_ctx->grantImplicitConfirm
/* do not set if polling starts: */
&& certOut != NULL))
goto err;
}
msg = ossl_cmp_certrep_new(srv_ctx->ctx, bodytype, certReqId, si,
certOut, NULL /* enc */, chainOut, caPubs,
srv_ctx->sendUnprotectedErrors);
if (msg == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREP);
err:
OSSL_CMP_PKISI_free(si);
X509_free(certOut);
sk_X509_pop_free(chainOut, X509_free);
sk_X509_pop_free(caPubs, X509_free);
return msg;
}
static OSSL_CMP_MSG *process_rr(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_REVDETAILS *details;
OSSL_CRMF_CERTID *certId = NULL;
OSSL_CRMF_CERTTEMPLATE *tmpl;
const X509_NAME *issuer;
const ASN1_INTEGER *serial;
OSSL_CMP_PKISI *si;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
if (sk_OSSL_CMP_REVDETAILS_num(req->body->value.rr) != 1) {
ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
if ((details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr,
OSSL_CMP_REVREQSID)) == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
return NULL;
}
tmpl = details->certDetails;
issuer = OSSL_CRMF_CERTTEMPLATE_get0_issuer(tmpl);
serial = OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(tmpl);
if (issuer != NULL && serial != NULL
&& (certId = OSSL_CRMF_CERTID_gen(issuer, serial)) == NULL)
return NULL;
if ((si = srv_ctx->process_rr(srv_ctx, req, issuer, serial)) == NULL)
goto err;
if ((msg = ossl_cmp_rp_new(srv_ctx->ctx, si, certId,
srv_ctx->sendUnprotectedErrors)) == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_RR);
err:
OSSL_CRMF_CERTID_free(certId);
OSSL_CMP_PKISI_free(si);
return msg;
}
/*
* Processes genm and creates a genp message mirroring the contents of the
* incoming message
*/
static OSSL_CMP_MSG *process_genm(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_GENMSGCONTENT *itavs;
OSSL_CMP_MSG *msg;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
if (!srv_ctx->process_genm(srv_ctx, req, req->body->value.genm, &itavs))
return NULL;
msg = ossl_cmp_genp_new(srv_ctx->ctx, itavs);
sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
return msg;
}
static OSSL_CMP_MSG *process_error(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_ERRORMSGCONTENT *errorContent;
OSSL_CMP_MSG *msg;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
errorContent = req->body->value.error;
srv_ctx->process_error(srv_ctx, req, errorContent->pKIStatusInfo,
errorContent->errorCode, errorContent->errorDetails);
if ((msg = ossl_cmp_pkiconf_new(srv_ctx->ctx)) == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_PKICONF);
return msg;
}
static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_CTX *ctx;
OSSL_CMP_CERTCONFIRMCONTENT *ccc;
int num;
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_CERTSTATUS *status = NULL;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
ctx = srv_ctx->ctx;
ccc = req->body->value.certConf;
num = sk_OSSL_CMP_CERTSTATUS_num(ccc);
if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM) == 1
|| ctx->status != OSSL_CMP_PKISTATUS_trans) {
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_UNEXPECTED_CERTCONF);
return NULL;
}
if (num == 0) {
ossl_cmp_err(ctx, "certificate rejected by client");
} else {
if (num > 1)
ossl_cmp_warn(ctx, "All CertStatus but the first will be ignored");
status = sk_OSSL_CMP_CERTSTATUS_value(ccc, OSSL_CMP_CERTREQID);
}
if (status != NULL) {
int certReqId = ossl_cmp_asn1_get_int(status->certReqId);
ASN1_OCTET_STRING *certHash = status->certHash;
OSSL_CMP_PKISI *si = status->statusInfo;
+ if (certReqId != srv_ctx->certReqId) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+ return NULL;
+ }
if (!srv_ctx->process_certConf(srv_ctx, req, certReqId, certHash, si))
return NULL; /* reason code may be: CMP_R_CERTHASH_UNMATCHED */
if (si != NULL
&& ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_accepted) {
int pki_status = ossl_cmp_pkisi_get_status(si);
const char *str = ossl_cmp_PKIStatus_to_string(pki_status);
ossl_cmp_log2(INFO, ctx, "certificate rejected by client %s %s",
str == NULL ? "without" : "with",
str == NULL ? "PKIStatus" : str);
}
}
if ((msg = ossl_cmp_pkiconf_new(ctx)) == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_PKICONF);
return msg;
}
static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_POLLREQCONTENT *prc;
OSSL_CMP_POLLREQ *pr;
int certReqId;
OSSL_CMP_MSG *certReq;
int64_t check_after = 0;
OSSL_CMP_MSG *msg = NULL;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
prc = req->body->value.pollReq;
if (sk_OSSL_CMP_POLLREQ_num(prc) != 1) {
ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
- pr = sk_OSSL_CMP_POLLREQ_value(prc, 0);
+ pr = sk_OSSL_CMP_POLLREQ_value(prc, OSSL_CMP_CERTREQID);
certReqId = ossl_cmp_asn1_get_int(pr->certReqId);
+ if (certReqId != srv_ctx->certReqId) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+ return NULL;
+ }
if (!srv_ctx->process_pollReq(srv_ctx, req, certReqId,
&certReq, &check_after))
return NULL;
if (certReq != NULL) {
msg = process_cert_request(srv_ctx, certReq);
OSSL_CMP_MSG_free(certReq);
} else {
if ((msg = ossl_cmp_pollRep_new(srv_ctx->ctx, certReqId,
check_after)) == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_POLLREP);
}
return msg;
}
/*
* Determine whether missing/invalid protection of request message is allowed.
* Return 1 on acceptance, 0 on rejection, or -1 on (internal) error.
*/
static int unprotected_exception(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *req,
int invalid_protection,
int accept_unprotected_requests)
{
if (!ossl_assert(ctx != NULL && req != NULL))
return -1;
if (accept_unprotected_requests) {
ossl_cmp_log1(WARN, ctx, "ignoring %s protection of request message",
invalid_protection ? "invalid" : "missing");
return 1;
}
if (OSSL_CMP_MSG_get_bodytype(req) == OSSL_CMP_PKIBODY_ERROR
&& OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS) == 1) {
ossl_cmp_warn(ctx, "ignoring missing protection of error message");
return 1;
}
return 0;
}
/*
* returns created message and NULL on internal error
*/
OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_CTX *ctx;
ASN1_OCTET_STRING *backup_secret;
OSSL_CMP_PKIHEADER *hdr;
int req_type, rsp_type;
- int res;
+ int req_verified = 0;
OSSL_CMP_MSG *rsp = NULL;
if (srv_ctx == NULL || srv_ctx->ctx == NULL
|| req == NULL || req->body == NULL
|| (hdr = OSSL_CMP_MSG_get0_header(req)) == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx = srv_ctx->ctx;
backup_secret = ctx->secretValue;
req_type = OSSL_CMP_MSG_get_bodytype(req);
ossl_cmp_log1(DEBUG, ctx,
"received %s", ossl_cmp_bodytype_to_string(req_type));
/*
* Some things need to be done already before validating the message in
* order to be able to send an error message as far as needed and possible.
*/
if (hdr->sender->type != GEN_DIRNAME) {
ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
goto err;
}
if (!OSSL_CMP_CTX_set1_recipient(ctx, hdr->sender->d.directoryName))
goto err;
switch (req_type) {
case OSSL_CMP_PKIBODY_IR:
case OSSL_CMP_PKIBODY_CR:
case OSSL_CMP_PKIBODY_P10CR:
case OSSL_CMP_PKIBODY_KUR:
case OSSL_CMP_PKIBODY_RR:
case OSSL_CMP_PKIBODY_GENM:
case OSSL_CMP_PKIBODY_ERROR:
if (ctx->transactionID != NULL) {
char *tid;
tid = OPENSSL_buf2hexstr(ctx->transactionID->data,
ctx->transactionID->length);
if (tid != NULL)
ossl_cmp_log1(WARN, ctx,
"Assuming that last transaction with ID=%s got aborted",
tid);
OPENSSL_free(tid);
}
/* start of a new transaction, reset transactionID and senderNonce */
if (!OSSL_CMP_CTX_set1_transactionID(ctx, NULL)
|| !OSSL_CMP_CTX_set1_senderNonce(ctx, NULL))
goto err;
break;
default:
/* transactionID should be already initialized */
if (ctx->transactionID == NULL) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
goto err;
#endif
}
}
- res = ossl_cmp_msg_check_update(ctx, req, unprotected_exception,
- srv_ctx->acceptUnprotected);
+ req_verified = ossl_cmp_msg_check_update(ctx, req, unprotected_exception,
+ srv_ctx->acceptUnprotected);
if (ctx->secretValue != NULL && ctx->pkey != NULL
&& ossl_cmp_hdr_get_protection_nid(hdr) != NID_id_PasswordBasedMAC)
ctx->secretValue = NULL; /* use MSG_SIG_ALG when protecting rsp */
- if (!res)
+ if (!req_verified)
goto err;
switch (req_type) {
case OSSL_CMP_PKIBODY_IR:
case OSSL_CMP_PKIBODY_CR:
case OSSL_CMP_PKIBODY_P10CR:
case OSSL_CMP_PKIBODY_KUR:
if (srv_ctx->process_cert_request == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_cert_request(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_RR:
if (srv_ctx->process_rr == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_rr(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_GENM:
if (srv_ctx->process_genm == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_genm(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_ERROR:
if (srv_ctx->process_error == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_error(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_CERTCONF:
if (srv_ctx->process_certConf == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_certConf(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_POLLREQ:
if (srv_ctx->process_pollReq == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_pollReq(srv_ctx, req);
break;
default:
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
break;
}
err:
if (rsp == NULL) {
/* on error, try to respond with CMP error message to client */
const char *data = NULL, *reason = NULL;
int flags = 0;
unsigned long err = ERR_peek_error_data(&data, &flags);
int fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_badRequest;
OSSL_CMP_PKISI *si = NULL;
- if (ctx->transactionID == NULL) {
- /* ignore any (extra) error in next two function calls: */
- (void)OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID);
+ if (!req_verified) {
+ /*
+ * Above ossl_cmp_msg_check_update() was not successfully executed,
+ * which normally would set ctx->transactionID and ctx->recipNonce.
+ * So anyway try to provide the right transactionID and recipNonce,
+ * while ignoring any (extra) error in next two function calls.
+ */
+ if (ctx->transactionID == NULL)
+ (void)OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID);
(void)ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce);
}
if ((flags & ERR_TXT_STRING) == 0 || *data == '\0')
data = NULL;
reason = ERR_reason_error_string(err);
if ((si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection,
fail_info, reason)) != NULL) {
rsp = ossl_cmp_error_new(srv_ctx->ctx, si, err,
data, srv_ctx->sendUnprotectedErrors);
OSSL_CMP_PKISI_free(si);
}
}
OSSL_CMP_CTX_print_errors(ctx);
ctx->secretValue = backup_secret;
rsp_type =
rsp != NULL ? OSSL_CMP_MSG_get_bodytype(rsp) : OSSL_CMP_PKIBODY_ERROR;
if (rsp != NULL)
ossl_cmp_log1(DEBUG, ctx,
"sending %s", ossl_cmp_bodytype_to_string(rsp_type));
else
ossl_cmp_log(ERR, ctx, "cannot send proper CMP response");
/* determine whether to keep the transaction open or not */
ctx->status = OSSL_CMP_PKISTATUS_trans;
switch (rsp_type) {
case OSSL_CMP_PKIBODY_IP:
case OSSL_CMP_PKIBODY_CP:
case OSSL_CMP_PKIBODY_KUP:
if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM) == 0)
break;
/* fall through */
case OSSL_CMP_PKIBODY_RP:
case OSSL_CMP_PKIBODY_PKICONF:
case OSSL_CMP_PKIBODY_GENP:
case OSSL_CMP_PKIBODY_ERROR:
(void)OSSL_CMP_CTX_set1_transactionID(ctx, NULL);
(void)OSSL_CMP_CTX_set1_senderNonce(ctx, NULL);
ctx->status = OSSL_CMP_PKISTATUS_unspecified; /* transaction closed */
default: /* not closing transaction in other cases */
break;
}
return rsp;
}
/*
* Server interface that may substitute OSSL_CMP_MSG_http_perform at the client.
* The OSSL_CMP_SRV_CTX must be set as client_ctx->transfer_cb_arg.
* returns received message on success, else NULL and pushes an element on the
* error stack.
*/
OSSL_CMP_MSG *OSSL_CMP_CTX_server_perform(OSSL_CMP_CTX *client_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_SRV_CTX *srv_ctx = NULL;
if (client_ctx == NULL || req == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return NULL;
}
if ((srv_ctx = OSSL_CMP_CTX_get_transfer_cb_arg(client_ctx)) == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_TRANSFER_ERROR);
return NULL;
}
return OSSL_CMP_SRV_process_request(srv_ctx, req);
}
diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c
index 99cd56cb091f..7ce91ec5d167 100644
--- a/crypto/cmp/cmp_vfy.c
+++ b/crypto/cmp/cmp_vfy.c
@@ -1,856 +1,855 @@
/*
- * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2020
* Copyright Siemens AG 2015-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
*/
/* CMP functions for PKIMessage checking */
#include "cmp_local.h"
#include <openssl/cmp_util.h>
/* explicit #includes not strictly needed since implied by the above: */
#include <openssl/asn1t.h>
#include <openssl/cmp.h>
#include <openssl/crmf.h>
#include <openssl/err.h>
#include <openssl/x509.h>
/* Verify a message protected by signature according to RFC section 5.1.3.3 */
static int verify_signature(const OSSL_CMP_CTX *cmp_ctx,
const OSSL_CMP_MSG *msg, X509 *cert)
{
OSSL_CMP_PROTECTEDPART prot_part;
EVP_PKEY *pubkey = NULL;
BIO *bio;
int res = 0;
if (!ossl_assert(cmp_ctx != NULL && msg != NULL && cert != NULL))
return 0;
bio = BIO_new(BIO_s_mem()); /* may be NULL */
/* verify that keyUsage, if present, contains digitalSignature */
if (!cmp_ctx->ignore_keyusage
&& (X509_get_key_usage(cert) & X509v3_KU_DIGITAL_SIGNATURE) == 0) {
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE);
goto sig_err;
}
pubkey = X509_get_pubkey(cert);
if (pubkey == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_FAILED_EXTRACTING_PUBKEY);
goto sig_err;
}
prot_part.header = msg->header;
prot_part.body = msg->body;
if (ASN1_item_verify_ex(ASN1_ITEM_rptr(OSSL_CMP_PROTECTEDPART),
msg->header->protectionAlg, msg->protection,
&prot_part, NULL, pubkey, cmp_ctx->libctx,
cmp_ctx->propq) > 0) {
res = 1;
goto end;
}
sig_err:
res = ossl_x509_print_ex_brief(bio, cert, X509_FLAG_NO_EXTENSIONS);
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_SIGNATURE);
if (res)
ERR_add_error_mem_bio("\n", bio);
res = 0;
end:
EVP_PKEY_free(pubkey);
BIO_free(bio);
return res;
}
/* Verify a message protected with PBMAC */
static int verify_PBMAC(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
{
ASN1_BIT_STRING *protection = NULL;
int valid = 0;
/* generate expected protection for the message */
if ((protection = ossl_cmp_calc_protection(ctx, msg)) == NULL)
return 0; /* failed to generate protection string! */
valid = msg->protection != NULL && msg->protection->length >= 0
&& msg->protection->type == protection->type
&& msg->protection->length == protection->length
&& CRYPTO_memcmp(msg->protection->data, protection->data,
protection->length) == 0;
ASN1_BIT_STRING_free(protection);
if (!valid)
ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_PBM_VALUE);
return valid;
}
/*-
* Attempt to validate certificate and path using any given store with trusted
* certs (possibly including CRLs and a cert verification callback function)
* and non-trusted intermediate certs from the given ctx.
*
* Returns 1 on successful validation and 0 otherwise.
*/
int OSSL_CMP_validate_cert_path(const OSSL_CMP_CTX *ctx,
X509_STORE *trusted_store, X509 *cert)
{
int valid = 0;
X509_STORE_CTX *csc = NULL;
int err;
if (ctx == NULL || cert == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (trusted_store == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_TRUST_STORE);
return 0;
}
if ((csc = X509_STORE_CTX_new_ex(ctx->libctx, ctx->propq)) == NULL
|| !X509_STORE_CTX_init(csc, trusted_store,
cert, ctx->untrusted))
goto err;
valid = X509_verify_cert(csc) > 0;
/* make sure suitable error is queued even if callback did not do */
err = ERR_peek_last_error();
if (!valid && ERR_GET_REASON(err) != CMP_R_POTENTIALLY_INVALID_CERTIFICATE)
ERR_raise(ERR_LIB_CMP, CMP_R_POTENTIALLY_INVALID_CERTIFICATE);
err:
/* directly output any fresh errors, needed for check_msg_find_cert() */
OSSL_CMP_CTX_print_errors(ctx);
X509_STORE_CTX_free(csc);
return valid;
}
/* Return 0 if expect_name != NULL and there is no matching actual_name */
static int check_name(const OSSL_CMP_CTX *ctx, int log_success,
const char *actual_desc, const X509_NAME *actual_name,
const char *expect_desc, const X509_NAME *expect_name)
{
char *str;
if (expect_name == NULL)
return 1; /* no expectation, thus trivially fulfilled */
/* make sure that a matching name is there */
if (actual_name == NULL) {
ossl_cmp_log1(WARN, ctx, "missing %s", actual_desc);
return 0;
}
str = X509_NAME_oneline(actual_name, NULL, 0);
if (X509_NAME_cmp(actual_name, expect_name) == 0) {
if (log_success && str != NULL)
ossl_cmp_log2(INFO, ctx, " subject matches %s: %s", expect_desc,
str);
OPENSSL_free(str);
return 1;
}
if (str != NULL)
ossl_cmp_log2(INFO, ctx, " actual name in %s = %s", actual_desc, str);
OPENSSL_free(str);
if ((str = X509_NAME_oneline(expect_name, NULL, 0)) != NULL)
ossl_cmp_log2(INFO, ctx, " does not match %s = %s", expect_desc, str);
OPENSSL_free(str);
return 0;
}
/* Return 0 if skid != NULL and there is no matching subject key ID in cert */
static int check_kid(const OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *ckid,
const ASN1_OCTET_STRING *skid)
{
char *str;
if (skid == NULL)
return 1; /* no expectation, thus trivially fulfilled */
/* make sure that the expected subject key identifier is there */
if (ckid == NULL) {
ossl_cmp_warn(ctx, "missing Subject Key Identifier in certificate");
return 0;
}
str = OPENSSL_buf2hexstr(ckid->data, ckid->length);
if (ASN1_OCTET_STRING_cmp(ckid, skid) == 0) {
if (str != NULL)
ossl_cmp_log1(INFO, ctx, " subjectKID matches senderKID: %s", str);
OPENSSL_free(str);
return 1;
}
if (str != NULL)
ossl_cmp_log1(INFO, ctx, " cert Subject Key Identifier = %s", str);
OPENSSL_free(str);
if ((str = OPENSSL_buf2hexstr(skid->data, skid->length)) != NULL)
ossl_cmp_log1(INFO, ctx, " does not match senderKID = %s", str);
OPENSSL_free(str);
return 0;
}
static int already_checked(const X509 *cert,
const STACK_OF(X509) *already_checked)
{
int i;
for (i = sk_X509_num(already_checked /* may be NULL */); i > 0; i--)
if (X509_cmp(sk_X509_value(already_checked, i - 1), cert) == 0)
return 1;
return 0;
}
/*-
* Check if the given cert is acceptable as sender cert of the given message.
* The subject DN must match, the subject key ID as well if present in the msg,
* and the cert must be current (checked if ctx->trusted is not NULL).
* Note that cert revocation etc. is checked by OSSL_CMP_validate_cert_path().
*
* Returns 0 on error or not acceptable, else 1.
*/
static int cert_acceptable(const OSSL_CMP_CTX *ctx,
const char *desc1, const char *desc2, X509 *cert,
const STACK_OF(X509) *already_checked1,
const STACK_OF(X509) *already_checked2,
const OSSL_CMP_MSG *msg)
{
X509_STORE *ts = ctx->trusted;
int self_issued = X509_check_issued(cert, cert) == X509_V_OK;
char *str;
X509_VERIFY_PARAM *vpm = ts != NULL ? X509_STORE_get0_param(ts) : NULL;
int time_cmp;
ossl_cmp_log3(INFO, ctx, " considering %s%s %s with..",
self_issued ? "self-issued ": "", desc1, desc2);
if ((str = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0)) != NULL)
ossl_cmp_log1(INFO, ctx, " subject = %s", str);
OPENSSL_free(str);
if (!self_issued) {
str = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
if (str != NULL)
ossl_cmp_log1(INFO, ctx, " issuer = %s", str);
OPENSSL_free(str);
}
if (already_checked(cert, already_checked1)
|| already_checked(cert, already_checked2)) {
ossl_cmp_info(ctx, " cert has already been checked");
return 0;
}
time_cmp = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert),
X509_get0_notAfter(cert));
if (time_cmp != 0) {
ossl_cmp_warn(ctx, time_cmp > 0 ? "cert has expired"
: "cert is not yet valid");
return 0;
}
if (!check_name(ctx, 1,
"cert subject", X509_get_subject_name(cert),
"sender field", msg->header->sender->d.directoryName))
return 0;
if (!check_kid(ctx, X509_get0_subject_key_id(cert), msg->header->senderKID))
return 0;
/* prevent misleading error later in case x509v3_cache_extensions() fails */
if (!ossl_x509v3_cache_extensions(cert)) {
ossl_cmp_warn(ctx, "cert appears to be invalid");
return 0;
}
if (!verify_signature(ctx, msg, cert)) {
ossl_cmp_warn(ctx, "msg signature verification failed");
return 0;
}
/* acceptable also if there is no senderKID in msg header */
ossl_cmp_info(ctx, " cert seems acceptable");
return 1;
}
static int check_cert_path(const OSSL_CMP_CTX *ctx, X509_STORE *store,
X509 *scrt)
{
if (OSSL_CMP_validate_cert_path(ctx, store, scrt))
return 1;
ossl_cmp_warn(ctx,
"msg signature validates but cert path validation failed");
return 0;
}
/*
* Exceptional handling for 3GPP TS 33.310 [3G/LTE Network Domain Security
* (NDS); Authentication Framework (AF)], only to use for IP messages
* and if the ctx option is explicitly set: use self-issued certificates
* from extraCerts as trust anchor to validate sender cert -
* provided it also can validate the newly enrolled certificate
*/
static int check_cert_path_3gpp(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *msg, X509 *scrt)
{
int valid = 0;
X509_STORE *store;
if (!ctx->permitTAInExtraCertsForIR)
return 0;
if ((store = X509_STORE_new()) == NULL
|| !ossl_cmp_X509_STORE_add1_certs(store, msg->extraCerts,
1 /* self-issued only */))
goto err;
/* store does not include CRLs */
valid = OSSL_CMP_validate_cert_path(ctx, store, scrt);
if (!valid) {
ossl_cmp_warn(ctx,
"also exceptional 3GPP mode cert path validation failed");
} else {
/*
* verify that the newly enrolled certificate (which assumed rid ==
* OSSL_CMP_CERTREQID) can also be validated with the same trusted store
*/
- EVP_PKEY *pkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
OSSL_CMP_CERTRESPONSE *crep =
ossl_cmp_certrepmessage_get0_certresponse(msg->body->value.ip,
OSSL_CMP_CERTREQID);
- X509 *newcrt = ossl_cmp_certresponse_get1_cert(crep, ctx, pkey);
+ X509 *newcrt = ossl_cmp_certresponse_get1_cert(ctx, crep);
+
/*
* maybe better use get_cert_status() from cmp_client.c, which catches
* errors
*/
valid = OSSL_CMP_validate_cert_path(ctx, store, newcrt);
X509_free(newcrt);
}
err:
X509_STORE_free(store);
return valid;
}
static int check_msg_given_cert(const OSSL_CMP_CTX *ctx, X509 *cert,
const OSSL_CMP_MSG *msg)
{
return cert_acceptable(ctx, "previously validated", "sender cert",
cert, NULL, NULL, msg)
&& (check_cert_path(ctx, ctx->trusted, cert)
|| check_cert_path_3gpp(ctx, msg, cert));
}
/*-
* Try all certs in given list for verifying msg, normally or in 3GPP mode.
* If already_checked1 == NULL then certs are assumed to be the msg->extraCerts.
* On success cache the found cert using ossl_cmp_ctx_set0_validatedSrvCert().
*/
static int check_msg_with_certs(OSSL_CMP_CTX *ctx, const STACK_OF(X509) *certs,
const char *desc,
const STACK_OF(X509) *already_checked1,
const STACK_OF(X509) *already_checked2,
const OSSL_CMP_MSG *msg, int mode_3gpp)
{
int in_extraCerts = already_checked1 == NULL;
int n_acceptable_certs = 0;
int i;
if (sk_X509_num(certs) <= 0) {
ossl_cmp_log1(WARN, ctx, "no %s", desc);
return 0;
}
for (i = 0; i < sk_X509_num(certs); i++) { /* certs may be NULL */
X509 *cert = sk_X509_value(certs, i);
if (!ossl_assert(cert != NULL))
return 0;
if (!cert_acceptable(ctx, "cert from", desc, cert,
already_checked1, already_checked2, msg))
continue;
n_acceptable_certs++;
if (mode_3gpp ? check_cert_path_3gpp(ctx, msg, cert)
: check_cert_path(ctx, ctx->trusted, cert)) {
/* store successful sender cert for further msgs in transaction */
if (!X509_up_ref(cert))
return 0;
if (!ossl_cmp_ctx_set0_validatedSrvCert(ctx, cert)) {
X509_free(cert);
return 0;
}
return 1;
}
}
if (in_extraCerts && n_acceptable_certs == 0)
ossl_cmp_warn(ctx, "no acceptable cert in extraCerts");
return 0;
}
/*-
* Verify msg trying first ctx->untrusted, which should include extraCerts
* at its front, then trying the trusted certs in truststore (if any) of ctx.
* On success cache the found cert using ossl_cmp_ctx_set0_validatedSrvCert().
*/
static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
int mode_3gpp)
{
int ret = 0;
if (mode_3gpp
&& ((!ctx->permitTAInExtraCertsForIR
|| OSSL_CMP_MSG_get_bodytype(msg) != OSSL_CMP_PKIBODY_IP)))
return 0;
ossl_cmp_info(ctx,
mode_3gpp ? "normal mode failed; trying now 3GPP mode trusting extraCerts"
: "trying first normal mode using trust store");
if (check_msg_with_certs(ctx, msg->extraCerts, "extraCerts",
NULL, NULL, msg, mode_3gpp))
return 1;
if (check_msg_with_certs(ctx, ctx->untrusted, "untrusted certs",
msg->extraCerts, NULL, msg, mode_3gpp))
return 1;
if (ctx->trusted == NULL) {
ossl_cmp_warn(ctx, mode_3gpp ? "no self-issued extraCerts"
: "no trusted store");
} else {
STACK_OF(X509) *trusted = X509_STORE_get1_all_certs(ctx->trusted);
ret = check_msg_with_certs(ctx, trusted,
mode_3gpp ? "self-issued extraCerts"
: "certs in trusted store",
msg->extraCerts, ctx->untrusted,
msg, mode_3gpp);
sk_X509_pop_free(trusted, X509_free);
}
return ret;
}
static int no_log_cb(const char *func, const char *file, int line,
OSSL_CMP_severity level, const char *msg)
{
return 1;
}
/*-
* Verify message signature with any acceptable and valid candidate cert.
* On success cache the found cert using ossl_cmp_ctx_set0_validatedSrvCert().
*/
static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
{
X509 *scrt = ctx->validatedSrvCert; /* previous successful sender cert */
GENERAL_NAME *sender = msg->header->sender;
char *sname = NULL;
char *skid_str = NULL;
const ASN1_OCTET_STRING *skid = msg->header->senderKID;
OSSL_CMP_log_cb_t backup_log_cb = ctx->log_cb;
int res = 0;
if (sender == NULL || msg->body == NULL)
return 0; /* other NULL cases already have been checked */
if (sender->type != GEN_DIRNAME) {
ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
return 0;
}
/* dump any hitherto errors to avoid confusion when printing further ones */
OSSL_CMP_CTX_print_errors(ctx);
/* enable clearing irrelevant errors in attempts to validate sender certs */
(void)ERR_set_mark();
ctx->log_cb = no_log_cb; /* temporarily disable logging */
/*
* try first cached scrt, used successfully earlier in same transaction,
* for validating this and any further msgs where extraCerts may be left out
*/
if (scrt != NULL) {
if (check_msg_given_cert(ctx, scrt, msg)) {
ctx->log_cb = backup_log_cb;
(void)ERR_pop_to_mark();
return 1;
}
/* cached sender cert has shown to be no more successfully usable */
(void)ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL);
/* re-do the above check (just) for adding diagnostic information */
ossl_cmp_info(ctx,
"trying to verify msg signature with previously validated cert");
(void)check_msg_given_cert(ctx, scrt, msg);
}
res = check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */)
|| check_msg_all_certs(ctx, msg, 1 /* 3gpp */);
ctx->log_cb = backup_log_cb;
if (res) {
/* discard any diagnostic information on trying to use certs */
(void)ERR_pop_to_mark();
goto end;
}
/* failed finding a sender cert that verifies the message signature */
(void)ERR_clear_last_mark();
sname = X509_NAME_oneline(sender->d.directoryName, NULL, 0);
skid_str = skid == NULL ? NULL
: OPENSSL_buf2hexstr(skid->data, skid->length);
if (ctx->log_cb != NULL) {
ossl_cmp_info(ctx, "trying to verify msg signature with a valid cert that..");
if (sname != NULL)
ossl_cmp_log1(INFO, ctx, "matches msg sender = %s", sname);
if (skid_str != NULL)
ossl_cmp_log1(INFO, ctx, "matches msg senderKID = %s", skid_str);
else
ossl_cmp_info(ctx, "while msg header does not contain senderKID");
/* re-do the above checks (just) for adding diagnostic information */
(void)check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */);
(void)check_msg_all_certs(ctx, msg, 1 /* 3gpp */);
}
ERR_raise(ERR_LIB_CMP, CMP_R_NO_SUITABLE_SENDER_CERT);
if (sname != NULL) {
ERR_add_error_txt(NULL, "for msg sender name = ");
ERR_add_error_txt(NULL, sname);
}
if (skid_str != NULL) {
ERR_add_error_txt(" and ", "for msg senderKID = ");
ERR_add_error_txt(NULL, skid_str);
}
end:
OPENSSL_free(sname);
OPENSSL_free(skid_str);
return res;
}
/*-
* Validate the protection of the given PKIMessage using either password-
* based mac (PBM) or a signature algorithm. In the case of signature algorithm,
* the sender certificate can have been pinned by providing it in ctx->srvCert,
* else it is searched in msg->extraCerts, ctx->untrusted, in ctx->trusted
* (in this order) and is path is validated against ctx->trusted.
* On success cache the found cert using ossl_cmp_ctx_set0_validatedSrvCert().
*
* If ctx->permitTAInExtraCertsForIR is true and when validating a CMP IP msg,
* the trust anchor for validating the IP msg may be taken from msg->extraCerts
* if a self-issued certificate is found there that can be used to
* validate the enrolled certificate returned in the IP.
* This is according to the need given in 3GPP TS 33.310.
*
* Returns 1 on success, 0 on error or validation failed.
*/
int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
{
X509 *scrt;
ossl_cmp_debug(ctx, "validating CMP message");
if (ctx == NULL || msg == NULL
|| msg->header == NULL || msg->body == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (msg->header->protectionAlg == NULL /* unprotected message */
|| msg->protection == NULL || msg->protection->data == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PROTECTION);
return 0;
}
switch (ossl_cmp_hdr_get_protection_nid(msg->header)) {
/* 5.1.3.1. Shared Secret Information */
case NID_id_PasswordBasedMAC:
if (ctx->secretValue == NULL) {
ossl_cmp_info(ctx, "no secret available for verifying PBM-based CMP message protection");
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_SECRET);
return 0;
}
if (verify_PBMAC(ctx, msg)) {
/*
* RFC 4210, 5.3.2: 'Note that if the PKI Message Protection is
* "shared secret information", then any certificate transported in
* the caPubs field may be directly trusted as a root CA
* certificate by the initiator.'
*/
switch (OSSL_CMP_MSG_get_bodytype(msg)) {
case -1:
return 0;
case OSSL_CMP_PKIBODY_IP:
case OSSL_CMP_PKIBODY_CP:
case OSSL_CMP_PKIBODY_KUP:
case OSSL_CMP_PKIBODY_CCP:
if (ctx->trusted != NULL) {
STACK_OF(X509) *certs = msg->body->value.ip->caPubs;
/* value.ip is same for cp, kup, and ccp */
if (!ossl_cmp_X509_STORE_add1_certs(ctx->trusted, certs, 0))
/* adds both self-issued and not self-issued certs */
return 0;
}
break;
default:
break;
}
ossl_cmp_debug(ctx,
"sucessfully validated PBM-based CMP message protection");
return 1;
}
ossl_cmp_warn(ctx, "verifying PBM-based CMP message protection failed");
break;
/*
* 5.1.3.2 DH Key Pairs
* Not yet supported
*/
case NID_id_DHBasedMac:
ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC);
break;
/*
* 5.1.3.3. Signature
*/
default:
scrt = ctx->srvCert;
if (scrt == NULL) {
if (ctx->trusted == NULL) {
ossl_cmp_info(ctx, "no trust store nor pinned server cert available for verifying signature-based CMP message protection");
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_TRUST_ANCHOR);
return 0;
}
if (check_msg_find_cert(ctx, msg))
return 1;
} else { /* use pinned sender cert */
/* use ctx->srvCert for signature check even if not acceptable */
if (verify_signature(ctx, msg, scrt)) {
ossl_cmp_debug(ctx,
"sucessfully validated signature-based CMP message protection");
return 1;
}
ossl_cmp_warn(ctx, "CMP message signature verification failed");
ERR_raise(ERR_LIB_CMP, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG);
}
break;
}
return 0;
}
-
/*-
* Check received message (i.e., response by server or request from client)
* Any msg->extraCerts are prepended to ctx->untrusted.
*
* Ensures that:
* its sender is of appropriate type (curently only X509_NAME) and
* matches any expected sender or srvCert subject given in the ctx
* it has a valid body type
* its protection is valid (or invalid/absent, but only if a callback function
* is present and yields a positive result using also the supplied argument)
* its transaction ID matches the previous transaction ID stored in ctx (if any)
* its recipNonce matches the previous senderNonce stored in the ctx (if any)
*
* If everything is fine:
* learns the senderNonce from the received message,
* learns the transaction ID if it is not yet in ctx,
* and makes any certs in caPubs directly trusted.
*
* Returns 1 on success, 0 on error.
*/
int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
ossl_cmp_allow_unprotected_cb_t cb, int cb_arg)
{
OSSL_CMP_PKIHEADER *hdr;
const X509_NAME *expected_sender;
if (!ossl_assert(ctx != NULL && msg != NULL && msg->header != NULL))
return 0;
hdr = OSSL_CMP_MSG_get0_header(msg);
/* validate sender name of received msg */
if (hdr->sender->type != GEN_DIRNAME) {
ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
return 0;
}
/*
* Compare actual sender name of response with expected sender name.
* Mitigates risk to accept misused PBM secret
* or misused certificate of an unauthorized entity of a trusted hierarchy.
*/
expected_sender = ctx->expected_sender;
if (expected_sender == NULL && ctx->srvCert != NULL)
expected_sender = X509_get_subject_name(ctx->srvCert);
if (!check_name(ctx, 0, "sender DN field", hdr->sender->d.directoryName,
"expected sender", expected_sender))
return 0;
/* Note: if recipient was NULL-DN it could be learned here if needed */
if (sk_X509_num(msg->extraCerts) > 10)
ossl_cmp_warn(ctx,
"received CMP message contains more than 10 extraCerts");
/*
* Store any provided extraCerts in ctx for use in OSSL_CMP_validate_msg()
* and for future use, such that they are available to ctx->certConf_cb and
* the peer does not need to send them again in the same transaction.
* Note that it does not help validating the message before storing the
* extraCerts because they do not belong to the protected msg part anyway.
* For efficiency, the extraCerts are prepended so they get used first.
*/
if (!X509_add_certs(ctx->untrusted, msg->extraCerts,
/* this allows self-signed certs */
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
| X509_ADD_FLAG_PREPEND))
return 0;
/* validate message protection */
if (hdr->protectionAlg != NULL) {
/* detect explicitly permitted exceptions for invalid protection */
if (!OSSL_CMP_validate_msg(ctx, msg)
&& (cb == NULL || (*cb)(ctx, msg, 1, cb_arg) <= 0)) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_PROTECTION);
return 0;
#endif
}
} else {
/* detect explicitly permitted exceptions for missing protection */
if (cb == NULL || (*cb)(ctx, msg, 0, cb_arg) <= 0) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PROTECTION);
return 0;
#endif
}
}
/* check CMP version number in header */
if (ossl_cmp_hdr_get_pvno(hdr) != OSSL_CMP_PVNO) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PVNO);
return 0;
#endif
}
if (OSSL_CMP_MSG_get_bodytype(msg) < 0) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ERR_raise(ERR_LIB_CMP, CMP_R_PKIBODY_ERROR);
return 0;
#endif
}
/* compare received transactionID with the expected one in previous msg */
if (ctx->transactionID != NULL
&& (hdr->transactionID == NULL
|| ASN1_OCTET_STRING_cmp(ctx->transactionID,
hdr->transactionID) != 0)) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ERR_raise(ERR_LIB_CMP, CMP_R_TRANSACTIONID_UNMATCHED);
return 0;
#endif
}
/* compare received nonce with the one we sent */
if (ctx->senderNonce != NULL
&& (msg->header->recipNonce == NULL
|| ASN1_OCTET_STRING_cmp(ctx->senderNonce,
hdr->recipNonce) != 0)) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ERR_raise(ERR_LIB_CMP, CMP_R_RECIPNONCE_UNMATCHED);
return 0;
#endif
}
+ /* if not yet present, learn transactionID */
+ if (ctx->transactionID == NULL
+ && !OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID))
+ return 0;
+
/*
* RFC 4210 section 5.1.1 states: the recipNonce is copied from
* the senderNonce of the previous message in the transaction.
* --> Store for setting in next message
*/
if (!ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce))
return 0;
- /* if not yet present, learn transactionID */
- if (ctx->transactionID == NULL
- && !OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID))
- return -1;
-
/*
* Store any provided extraCerts in ctx for future use,
* such that they are available to ctx->certConf_cb and
* the peer does not need to send them again in the same transaction.
* For efficiency, the extraCerts are prepended so they get used first.
*/
if (!X509_add_certs(ctx->untrusted, msg->extraCerts,
/* this allows self-signed certs */
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
| X509_ADD_FLAG_PREPEND))
- return -1;
+ return 0;
if (ossl_cmp_hdr_get_protection_nid(hdr) == NID_id_PasswordBasedMAC) {
/*
* RFC 4210, 5.3.2: 'Note that if the PKI Message Protection is
* "shared secret information", then any certificate transported in
* the caPubs field may be directly trusted as a root CA
* certificate by the initiator.'
*/
switch (OSSL_CMP_MSG_get_bodytype(msg)) {
case OSSL_CMP_PKIBODY_IP:
case OSSL_CMP_PKIBODY_CP:
case OSSL_CMP_PKIBODY_KUP:
case OSSL_CMP_PKIBODY_CCP:
if (ctx->trusted != NULL) {
STACK_OF(X509) *certs = msg->body->value.ip->caPubs;
/* value.ip is same for cp, kup, and ccp */
if (!ossl_cmp_X509_STORE_add1_certs(ctx->trusted, certs, 0))
/* adds both self-issued and not self-issued certs */
return 0;
}
break;
default:
break;
}
}
return 1;
}
int ossl_cmp_verify_popo(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *msg, int acceptRAVerified)
{
if (!ossl_assert(msg != NULL && msg->body != NULL))
return 0;
switch (msg->body->type) {
case OSSL_CMP_PKIBODY_P10CR:
{
X509_REQ *req = msg->body->value.p10cr;
if (X509_REQ_verify_ex(req, X509_REQ_get0_pubkey(req), ctx->libctx,
ctx->propq) <= 0) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ERR_raise(ERR_LIB_CMP, CMP_R_REQUEST_NOT_ACCEPTED);
return 0;
#endif
}
}
break;
case OSSL_CMP_PKIBODY_IR:
case OSSL_CMP_PKIBODY_CR:
case OSSL_CMP_PKIBODY_KUR:
if (!OSSL_CRMF_MSGS_verify_popo(msg->body->value.ir, OSSL_CMP_CERTREQID,
acceptRAVerified,
ctx->libctx, ctx->propq)) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
return 0;
#endif
}
break;
default:
ERR_raise(ERR_LIB_CMP, CMP_R_PKIBODY_ERROR);
return 0;
}
return 1;
}
diff --git a/crypto/cms/cms_dh.c b/crypto/cms/cms_dh.c
index 7cc36f835f21..9509796317b3 100644
--- a/crypto/cms/cms_dh.c
+++ b/crypto/cms/cms_dh.c
@@ -1,343 +1,343 @@
/*
- * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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)
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 (penc == NULL || penclen == 0)
+ 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;
X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH),
V_ASN1_SEQUENCE, wrap_str);
rv = 1;
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/cms/cms_ec.c b/crypto/cms/cms_ec.c
index 8ecf730aa7b0..d5ebe1ced0a6 100644
--- a/crypto/cms/cms_ec.c
+++ b/crypto/cms/cms_ec.c
@@ -1,413 +1,417 @@
/*
- * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <limits.h>
#include <openssl/cms.h>
#include <openssl/err.h>
#include <openssl/decoder.h>
#include "internal/sizes.h"
#include "crypto/evp.h"
#include "cms_local.h"
static EVP_PKEY *pkey_type2param(int ptype, const void *pval,
OSSL_LIB_CTX *libctx, const char *propq)
{
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *pctx = NULL;
OSSL_DECODER_CTX *ctx = NULL;
if (ptype == V_ASN1_SEQUENCE) {
const ASN1_STRING *pstr = pval;
const unsigned char *pm = pstr->data;
size_t pmlen = (size_t)pstr->length;
int selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
ctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, "EC",
selection, libctx, propq);
if (ctx == NULL)
goto err;
if (!OSSL_DECODER_from_data(ctx, &pm, &pmlen)) {
ERR_raise(ERR_LIB_CMS, CMS_R_DECODE_ERROR);
goto err;
}
OSSL_DECODER_CTX_free(ctx);
return pkey;
} else if (ptype == V_ASN1_OBJECT) {
const ASN1_OBJECT *poid = pval;
char groupname[OSSL_MAX_NAME_SIZE];
/* type == V_ASN1_OBJECT => the parameters are given by an asn1 OID */
pctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", propq);
if (pctx == NULL || EVP_PKEY_paramgen_init(pctx) <= 0)
goto err;
if (OBJ_obj2txt(groupname, sizeof(groupname), poid, 0) <= 0
|| EVP_PKEY_CTX_set_group_name(pctx, groupname) <= 0) {
ERR_raise(ERR_LIB_CMS, CMS_R_DECODE_ERROR);
goto err;
}
if (EVP_PKEY_paramgen(pctx, &pkey) <= 0)
goto err;
EVP_PKEY_CTX_free(pctx);
return pkey;
}
ERR_raise(ERR_LIB_CMS, CMS_R_DECODE_ERROR);
return NULL;
err:
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(pctx);
OSSL_DECODER_CTX_free(ctx);
return NULL;
}
static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
{
const ASN1_OBJECT *aoid;
int atype;
const void *aval;
int rv = 0;
EVP_PKEY *pkpeer = NULL;
const unsigned char *p;
int plen;
X509_ALGOR_get0(&aoid, &atype, &aval, alg);
if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey)
goto err;
/* If absent parameters get group from main key */
if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) {
EVP_PKEY *pk;
pk = EVP_PKEY_CTX_get0_pkey(pctx);
if (pk == NULL)
goto err;
pkpeer = EVP_PKEY_new();
if (pkpeer == NULL)
goto err;
if (!EVP_PKEY_copy_parameters(pkpeer, pk))
goto err;
} else {
pkpeer = pkey_type2param(atype, aval,
EVP_PKEY_CTX_get0_libctx(pctx),
EVP_PKEY_CTX_get0_propq(pctx));
if (pkpeer == NULL)
goto err;
}
/* We have parameters now set public key */
plen = ASN1_STRING_length(pubkey);
p = ASN1_STRING_get0_data(pubkey);
if (p == NULL || plen == 0)
goto err;
if (!EVP_PKEY_set1_encoded_public_key(pkpeer, p, plen))
goto err;
if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
rv = 1;
err:
EVP_PKEY_free(pkpeer);
return rv;
}
/* Set KDF parameters based on KDF NID */
static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid)
{
int kdf_nid, kdfmd_nid, cofactor;
const EVP_MD *kdf_md;
if (eckdf_nid == NID_undef)
return 0;
/* Lookup KDF type, cofactor mode and digest */
if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid))
return 0;
if (kdf_nid == NID_dh_std_kdf)
cofactor = 0;
else if (kdf_nid == NID_dh_cofactor_kdf)
cofactor = 1;
else
return 0;
if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0)
return 0;
if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0)
return 0;
kdf_md = EVP_get_digestbynid(kdfmd_nid);
if (!kdf_md)
return 0;
if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
return 0;
return 1;
}
static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
{
int rv = 0;
X509_ALGOR *alg, *kekalg = NULL;
ASN1_OCTET_STRING *ukm;
const unsigned char *p;
unsigned char *der = NULL;
int plen, keylen;
EVP_CIPHER *kekcipher = NULL;
EVP_CIPHER_CTX *kekctx;
char name[OSSL_MAX_NAME_SIZE];
if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
return 0;
if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) {
ERR_raise(ERR_LIB_CMS, CMS_R_KDF_PARAMETER_ERROR);
return 0;
}
if (alg->parameter->type != V_ASN1_SEQUENCE)
return 0;
p = alg->parameter->value.sequence->data;
plen = alg->parameter->value.sequence->length;
kekalg = d2i_X509_ALGOR(NULL, &p, plen);
if (kekalg == NULL)
goto err;
kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
if (kekctx == NULL)
goto err;
OBJ_obj2txt(name, sizeof(name), kekalg->algorithm, 0);
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_ecdh_kdf_outlen(pctx, keylen) <= 0)
goto err;
plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen);
if (plen <= 0)
goto err;
if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0)
goto err;
der = NULL;
rv = 1;
err:
EVP_CIPHER_free(kekcipher);
X509_ALGOR_free(kekalg);
OPENSSL_free(der);
return rv;
}
static int ecdh_cms_decrypt(CMS_RecipientInfo *ri)
{
EVP_PKEY_CTX *pctx;
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (pctx == 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 (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) {
ERR_raise(ERR_LIB_CMS, CMS_R_PEER_KEY_ERROR);
return 0;
}
}
/* Set ECDH derivation parameters and initialise unwrap context */
if (!ecdh_cms_set_shared_info(pctx, ri)) {
ERR_raise(ERR_LIB_CMS, CMS_R_SHARED_INFO_ERROR);
return 0;
}
return 1;
}
static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
{
EVP_PKEY_CTX *pctx;
EVP_PKEY *pkey;
EVP_CIPHER_CTX *ctx;
int keylen;
X509_ALGOR *talg, *wrap_alg = NULL;
const ASN1_OBJECT *aoid;
ASN1_BIT_STRING *pubkey;
ASN1_STRING *wrap_str;
ASN1_OCTET_STRING *ukm;
unsigned char *penc = NULL;
- size_t penclen;
+ int penclen;
int rv = 0;
int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
const EVP_MD *kdf_md;
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (pctx == 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;
X509_ALGOR_get0(&aoid, NULL, NULL, talg);
/* Is everything uninitialised? */
if (aoid == OBJ_nid2obj(NID_undef)) {
/* Set the key */
+ size_t enckeylen;
- penclen = EVP_PKEY_get1_encoded_public_key(pkey, &penc);
- ASN1_STRING_set0(pubkey, penc, penclen);
+ enckeylen = EVP_PKEY_get1_encoded_public_key(pkey, &penc);
+ if (enckeylen > INT_MAX || enckeylen == 0)
+ goto err;
+ ASN1_STRING_set0(pubkey, penc, (int)enckeylen);
pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
penc = NULL;
- X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
- V_ASN1_UNDEF, NULL);
+ (void)X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
+ V_ASN1_UNDEF, NULL); /* cannot fail */
}
/* See if custom parameters set */
kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
if (kdf_type <= 0)
goto err;
if (EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md) <= 0)
goto err;
ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx);
if (ecdh_nid < 0)
goto err;
else if (ecdh_nid == 0)
ecdh_nid = NID_dh_std_kdf;
else if (ecdh_nid == 1)
ecdh_nid = NID_dh_cofactor_kdf;
if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
kdf_type = EVP_PKEY_ECDH_KDF_X9_63;
if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
goto err;
} else
/* Unknown KDF */
goto err;
if (kdf_md == NULL) {
/* Fixme later for better MD */
kdf_md = EVP_sha1();
if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
goto err;
}
if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
goto err;
/* Lookup NID for KDF+cofactor+digest */
if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_get_type(kdf_md), ecdh_nid))
goto err;
/* Get wrap NID */
ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
wrap_nid = EVP_CIPHER_CTX_get_type(ctx);
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_ecdh_kdf_outlen(pctx, keylen) <= 0)
goto err;
penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen);
- if (penclen == 0)
+ if (penclen <= 0)
goto err;
if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0)
goto err;
penc = NULL;
/*
* Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
* of another AlgorithmIdentifier.
*/
penclen = i2d_X509_ALGOR(wrap_alg, &penc);
- if (penc == NULL || penclen == 0)
+ 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;
X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str);
rv = 1;
err:
OPENSSL_free(penc);
X509_ALGOR_free(wrap_alg);
return rv;
}
int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt)
{
assert(decrypt == 0 || decrypt == 1);
if (decrypt == 1)
return ecdh_cms_decrypt(ri);
if (decrypt == 0)
return ecdh_cms_encrypt(ri);
ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
return 0;
}
/* ECDSA and DSA implementation is the same */
int ossl_cms_ecdsa_dsa_sign(CMS_SignerInfo *si, int verify)
{
assert(verify == 0 || verify == 1);
if (verify == 0) {
int snid, hnid;
X509_ALGOR *alg1, *alg2;
EVP_PKEY *pkey = si->pkey;
CMS_SignerInfo_get0_algs(si, NULL, NULL, &alg1, &alg2);
if (alg1 == NULL || alg1->algorithm == NULL)
return -1;
hnid = OBJ_obj2nid(alg1->algorithm);
if (hnid == NID_undef)
return -1;
if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_get_id(pkey)))
return -1;
X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
}
return 1;
}
diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c
index 51a1d7df848c..3105d37726a5 100644
--- a/crypto/cms/cms_env.c
+++ b/crypto/cms/cms_env.c
@@ -1,1336 +1,1336 @@
/*
- * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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(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:
ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
return 0;
}
}
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)
+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->encryptedContentInfo;
case CMS_ENVELOPED_AUTH:
return 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/cms/cms_lib.c b/crypto/cms/cms_lib.c
index 1fd542d2375c..0738da3da280 100644
--- a/crypto/cms/cms_lib.c
+++ b/crypto/cms/cms_lib.c
@@ -1,731 +1,732 @@
/*
- * Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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_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) {
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)) {
+ 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)
{
- int r;
- r = CMS_add0_crl(cms, crl);
- if (r > 0)
- X509_CRL_up_ref(crl);
- return r;
+ 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/cms/cms_smime.c b/crypto/cms/cms_smime.c
index d17df31dd412..479038d5732f 100644
--- a/crypto/cms/cms_smime.c
+++ b/crypto/cms/cms_smime.c
@@ -1,965 +1,976 @@
/*
- * Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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;
if (!(flags & CMS_DETACHED))
CMS_set_detached(cms, 0);
if ((flags & (CMS_STREAM | CMS_PARTIAL))
|| CMS_final(cms, in, NULL, flags))
return cms;
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;
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);
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;
+ 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);
- ris = CMS_get0_RecipientInfos(cms);
- if (ris != NULL)
- debug = ossl_cms_get0_env_enc_content(cms)->debug;
+ /* 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 otherwise try them
- * all.
- */
- else if (cert == NULL|| !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
+ /* 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;
}
- ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
+ 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;
+ 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 otherwise try them
- * all.
- */
- if (id == NULL || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
+ /* 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();
}
}
- ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
+ 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;
+ STACK_OF(CMS_RecipientInfo) *ris = CMS_get0_RecipientInfos(cms);
CMS_RecipientInfo *ri;
- int i, r;
+ 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;
+ }
- 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_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;
}
- ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
+ 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;
- if (flags & CMS_DEBUG_DECRYPT)
- ossl_cms_get0_env_enc_content(cms)->debug = 1;
- else
- ossl_cms_get0_env_enc_content(cms)->debug = 0;
- if (cert == NULL)
- ossl_cms_get0_env_enc_content(cms)->havenocert = 1;
- else
- ossl_cms_get0_env_enc_content(cms)->havenocert = 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/conf/conf_def.c b/crypto/conf/conf_def.c
index b5d6668f4276..5acc90b69e1c 100644
--- a/crypto/conf/conf_def.c
+++ b/crypto/conf/conf_def.c
@@ -1,1007 +1,1024 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/* Part of the code in here was originally in conf.c, which is now removed */
#include <stdio.h>
#include <string.h>
#include "e_os.h" /* struct stat */
#ifdef __TANDEM
# include <sys/types.h> /* needed for stat.h */
# include <sys/stat.h> /* struct stat */
#endif
#include "internal/cryptlib.h"
#include "internal/o_dir.h"
#include <openssl/lhash.h>
#include <openssl/conf.h>
#include <openssl/conf_api.h>
#include "conf_local.h"
#include "conf_def.h"
#include <openssl/buffer.h>
#include <openssl/err.h>
#ifndef OPENSSL_NO_POSIX_IO
# include <sys/stat.h>
# ifdef _WIN32
# define stat _stat
# endif
#endif
#ifndef S_ISDIR
# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
#endif
/*
* The maximum length we can grow a value to after variable expansion. 64k
* should be more than enough for all reasonable uses.
*/
#define MAX_CONF_VALUE_LENGTH 65536
static int is_keytype(const CONF *conf, char c, unsigned short type);
static char *eat_ws(CONF *conf, char *p);
static void trim_ws(CONF *conf, char *start);
static char *eat_alpha_numeric(CONF *conf, char *p);
static void clear_comments(CONF *conf, char *p);
static int str_copy(CONF *conf, char *section, char **to, char *from);
static char *scan_quote(CONF *conf, char *p);
static char *scan_dquote(CONF *conf, char *p);
#define scan_esc(conf,p) (((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2)))
#ifndef OPENSSL_NO_POSIX_IO
static BIO *process_include(char *include, OPENSSL_DIR_CTX **dirctx,
char **dirpath);
static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx);
#endif
static CONF *def_create(CONF_METHOD *meth);
static int def_init_default(CONF *conf);
#ifndef OPENSSL_NO_DEPRECATED_3_0
static int def_init_WIN32(CONF *conf);
#endif
static int def_destroy(CONF *conf);
static int def_destroy_data(CONF *conf);
static int def_load(CONF *conf, const char *name, long *eline);
static int def_load_bio(CONF *conf, BIO *bp, long *eline);
static int def_dump(const CONF *conf, BIO *bp);
static int def_is_number(const CONF *conf, char c);
static int def_to_int(const CONF *conf, char c);
static CONF_METHOD default_method = {
"OpenSSL default",
def_create,
def_init_default,
def_destroy,
def_destroy_data,
def_load_bio,
def_dump,
def_is_number,
def_to_int,
def_load
};
CONF_METHOD *NCONF_default(void)
{
return &default_method;
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
static CONF_METHOD WIN32_method = {
"WIN32",
def_create,
def_init_WIN32,
def_destroy,
def_destroy_data,
def_load_bio,
def_dump,
def_is_number,
def_to_int,
def_load
};
CONF_METHOD *NCONF_WIN32(void)
{
return &WIN32_method;
}
#endif
static CONF *def_create(CONF_METHOD *meth)
{
CONF *ret;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret != NULL)
if (meth->init(ret) == 0) {
OPENSSL_free(ret);
ret = NULL;
}
return ret;
}
static int def_init_default(CONF *conf)
{
if (conf == NULL)
return 0;
memset(conf, 0, sizeof(*conf));
conf->meth = &default_method;
conf->meth_data = (void *)CONF_type_default;
return 1;
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
static int def_init_WIN32(CONF *conf)
{
if (conf == NULL)
return 0;
memset(conf, 0, sizeof(*conf));
conf->meth = &WIN32_method;
conf->meth_data = (void *)CONF_type_win32;
return 1;
}
#endif
static int def_destroy(CONF *conf)
{
if (def_destroy_data(conf)) {
OPENSSL_free(conf);
return 1;
}
return 0;
}
static int def_destroy_data(CONF *conf)
{
if (conf == NULL)
return 0;
_CONF_free_data(conf);
return 1;
}
static int def_load(CONF *conf, const char *name, long *line)
{
int ret;
BIO *in = NULL;
#ifdef OPENSSL_SYS_VMS
in = BIO_new_file(name, "r");
#else
in = BIO_new_file(name, "rb");
#endif
if (in == NULL) {
if (ERR_GET_REASON(ERR_peek_last_error()) == BIO_R_NO_SUCH_FILE)
ERR_raise(ERR_LIB_CONF, CONF_R_NO_SUCH_FILE);
else
ERR_raise(ERR_LIB_CONF, ERR_R_SYS_LIB);
return 0;
}
ret = def_load_bio(conf, in, line);
BIO_free(in);
return ret;
}
/* Parse a boolean value and fill in *flag. Return 0 on error. */
static int parsebool(const char *pval, int *flag)
{
if (OPENSSL_strcasecmp(pval, "on") == 0
|| OPENSSL_strcasecmp(pval, "true") == 0) {
*flag = 1;
} else if (OPENSSL_strcasecmp(pval, "off") == 0
|| OPENSSL_strcasecmp(pval, "false") == 0) {
*flag = 0;
} else {
ERR_raise(ERR_LIB_CONF, CONF_R_INVALID_PRAGMA);
return 0;
}
return 1;
}
static int def_load_bio(CONF *conf, BIO *in, long *line)
{
/* The macro BUFSIZE conflicts with a system macro in VxWorks */
#define CONFBUFSIZE 512
int bufnum = 0, i, ii;
BUF_MEM *buff = NULL;
char *s, *p, *end;
int again;
int first_call = 1;
long eline = 0;
char btmp[DECIMAL_SIZE(eline) + 1];
CONF_VALUE *v = NULL, *tv;
CONF_VALUE *sv = NULL;
char *section = NULL, *buf;
char *start, *psection, *pname;
void *h = (void *)(conf->data);
STACK_OF(BIO) *biosk = NULL;
#ifndef OPENSSL_NO_POSIX_IO
char *dirpath = NULL;
OPENSSL_DIR_CTX *dirctx = NULL;
#endif
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ int numincludes = 0;
+#endif
if ((buff = BUF_MEM_new()) == NULL) {
ERR_raise(ERR_LIB_CONF, ERR_R_BUF_LIB);
goto err;
}
section = OPENSSL_strdup("default");
if (section == NULL) {
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
if (_CONF_new_data(conf) == 0) {
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
sv = _CONF_new_section(conf, section);
if (sv == NULL) {
ERR_raise(ERR_LIB_CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
goto err;
}
bufnum = 0;
again = 0;
for (;;) {
if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
ERR_raise(ERR_LIB_CONF, ERR_R_BUF_LIB);
goto err;
}
p = &(buff->data[bufnum]);
*p = '\0';
read_retry:
if (in != NULL && BIO_gets(in, p, CONFBUFSIZE - 1) < 0)
goto err;
p[CONFBUFSIZE - 1] = '\0';
ii = i = strlen(p);
if (first_call) {
/* Other BOMs imply unsupported multibyte encoding,
* so don't strip them and let the error raise */
const unsigned char utf8_bom[3] = {0xEF, 0xBB, 0xBF};
if (i >= 3 && memcmp(p, utf8_bom, 3) == 0) {
memmove(p, p + 3, i - 3);
p[i - 3] = 0;
i -= 3;
ii -= 3;
}
first_call = 0;
}
if (i == 0 && !again) {
/* the currently processed BIO is NULL or at EOF */
BIO *parent;
#ifndef OPENSSL_NO_POSIX_IO
/* continue processing with the next file from directory */
if (dirctx != NULL) {
BIO *next;
if ((next = get_next_file(dirpath, &dirctx)) != NULL) {
BIO_vfree(in);
in = next;
goto read_retry;
} else {
OPENSSL_free(dirpath);
dirpath = NULL;
}
}
#endif
/* no more files in directory, continue with processing parent */
if ((parent = sk_BIO_pop(biosk)) == NULL) {
/* everything processed get out of the loop */
break;
} else {
BIO_vfree(in);
in = parent;
goto read_retry;
}
}
again = 0;
while (i > 0) {
if ((p[i - 1] != '\r') && (p[i - 1] != '\n'))
break;
else
i--;
}
/*
* we removed some trailing stuff so there is a new line on the end.
*/
if (ii && i == ii)
again = 1; /* long line */
else {
p[i] = '\0';
eline++; /* another input line */
}
/* we now have a line with trailing \r\n removed */
/* i is the number of bytes */
bufnum += i;
v = NULL;
/* check for line continuation */
if (bufnum >= 1) {
/*
* If we have bytes and the last char '\\' and second last char
* is not '\\'
*/
p = &(buff->data[bufnum - 1]);
if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) {
bufnum--;
again = 1;
}
}
if (again)
continue;
bufnum = 0;
buf = buff->data;
clear_comments(conf, buf);
s = eat_ws(conf, buf);
if (IS_EOF(conf, *s))
continue; /* blank line */
if (*s == '[') {
char *ss;
s++;
start = eat_ws(conf, s);
ss = start;
again:
end = eat_alpha_numeric(conf, ss);
p = eat_ws(conf, end);
if (*p != ']') {
if (*p != '\0' && ss != p) {
ss = p;
goto again;
}
ERR_raise(ERR_LIB_CONF, CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
goto err;
}
*end = '\0';
if (!str_copy(conf, NULL, &section, start))
goto err;
if ((sv = _CONF_get_section(conf, section)) == NULL)
sv = _CONF_new_section(conf, section);
if (sv == NULL) {
ERR_raise(ERR_LIB_CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
goto err;
}
continue;
} else {
pname = s;
end = eat_alpha_numeric(conf, s);
if ((end[0] == ':') && (end[1] == ':')) {
*end = '\0';
end += 2;
psection = pname;
pname = end;
end = eat_alpha_numeric(conf, end);
} else {
psection = section;
}
p = eat_ws(conf, end);
if (strncmp(pname, ".pragma", 7) == 0
&& (p != pname + 7 || *p == '=')) {
char *pval;
if (*p == '=') {
p++;
p = eat_ws(conf, p);
}
trim_ws(conf, p);
/* Pragma values take the form keyword:value */
pval = strchr(p, ':');
if (pval == NULL || pval == p || pval[1] == '\0') {
ERR_raise(ERR_LIB_CONF, CONF_R_INVALID_PRAGMA);
goto err;
}
*pval++ = '\0';
trim_ws(conf, p);
pval = eat_ws(conf, pval);
/*
* Known pragmas:
*
* dollarid takes "on", "true or "off", "false"
* abspath takes "on", "true or "off", "false"
* includedir directory prefix
*/
if (strcmp(p, "dollarid") == 0) {
if (!parsebool(pval, &conf->flag_dollarid))
goto err;
} else if (strcmp(p, "abspath") == 0) {
if (!parsebool(pval, &conf->flag_abspath))
goto err;
} else if (strcmp(p, "includedir") == 0) {
OPENSSL_free(conf->includedir);
if ((conf->includedir = OPENSSL_strdup(pval)) == NULL) {
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
}
/*
* We *ignore* any unknown pragma.
*/
continue;
} else if (strncmp(pname, ".include", 8) == 0
&& (p != pname + 8 || *p == '=')) {
char *include = NULL;
BIO *next;
const char *include_dir = ossl_safe_getenv("OPENSSL_CONF_INCLUDE");
char *include_path = NULL;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ /*
+ * The include processing below can cause the "conf" fuzzer to
+ * timeout due to the fuzzer inserting large and complicated
+ * includes - with a large amount of time spent in
+ * OPENSSL_strlcat/OPENSSL_strcpy. This is not a security
+ * concern because config files should never come from untrusted
+ * sources. We just set an arbitrary limit on the allowed
+ * number of includes when fuzzing to prevent this timeout.
+ */
+ if (numincludes++ > 10)
+ goto err;
+#endif
+
if (include_dir == NULL)
include_dir = conf->includedir;
if (*p == '=') {
p++;
p = eat_ws(conf, p);
}
trim_ws(conf, p);
if (!str_copy(conf, psection, &include, p))
goto err;
if (include_dir != NULL && !ossl_is_absolute_path(include)) {
size_t newlen = strlen(include_dir) + strlen(include) + 2;
include_path = OPENSSL_malloc(newlen);
if (include_path == NULL) {
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
OPENSSL_free(include);
goto err;
}
OPENSSL_strlcpy(include_path, include_dir, newlen);
if (!ossl_ends_with_dirsep(include_path))
OPENSSL_strlcat(include_path, "/", newlen);
OPENSSL_strlcat(include_path, include, newlen);
OPENSSL_free(include);
} else {
include_path = include;
}
if (conf->flag_abspath
&& !ossl_is_absolute_path(include_path)) {
ERR_raise(ERR_LIB_CONF, CONF_R_RELATIVE_PATH);
OPENSSL_free(include_path);
goto err;
}
/* get the BIO of the included file */
#ifndef OPENSSL_NO_POSIX_IO
next = process_include(include_path, &dirctx, &dirpath);
if (include_path != dirpath) {
/* dirpath will contain include in case of a directory */
OPENSSL_free(include_path);
}
#else
next = BIO_new_file(include_path, "r");
OPENSSL_free(include_path);
#endif
if (next != NULL) {
/* push the currently processing BIO onto stack */
if (biosk == NULL) {
if ((biosk = sk_BIO_new_null()) == NULL) {
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
BIO_free(next);
goto err;
}
}
if (!sk_BIO_push(biosk, in)) {
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
BIO_free(next);
goto err;
}
/* continue with reading from the included BIO */
in = next;
}
continue;
} else if (*p != '=') {
ERR_raise_data(ERR_LIB_CONF, CONF_R_MISSING_EQUAL_SIGN,
"HERE-->%s", p);
goto err;
}
*end = '\0';
p++;
start = eat_ws(conf, p);
trim_ws(conf, start);
if ((v = OPENSSL_malloc(sizeof(*v))) == NULL) {
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
v->name = OPENSSL_strdup(pname);
v->value = NULL;
if (v->name == NULL) {
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!str_copy(conf, psection, &(v->value), start))
goto err;
if (strcmp(psection, section) != 0) {
if ((tv = _CONF_get_section(conf, psection))
== NULL)
tv = _CONF_new_section(conf, psection);
if (tv == NULL) {
ERR_raise(ERR_LIB_CONF,
CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
goto err;
}
} else
tv = sv;
if (_CONF_add_string(conf, tv, v) == 0) {
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
v = NULL;
}
}
BUF_MEM_free(buff);
OPENSSL_free(section);
/*
* No need to pop, since we only get here if the stack is empty.
* If this causes a BIO leak, THE ISSUE IS SOMEWHERE ELSE!
*/
sk_BIO_free(biosk);
return 1;
err:
BUF_MEM_free(buff);
OPENSSL_free(section);
/*
* Since |in| is the first element of the stack and should NOT be freed
* here, we cannot use sk_BIO_pop_free(). Instead, we pop and free one
* BIO at a time, making sure that the last one popped isn't.
*/
while (sk_BIO_num(biosk) > 0) {
BIO *popped = sk_BIO_pop(biosk);
BIO_vfree(in);
in = popped;
}
sk_BIO_free(biosk);
#ifndef OPENSSL_NO_POSIX_IO
OPENSSL_free(dirpath);
if (dirctx != NULL)
OPENSSL_DIR_end(&dirctx);
#endif
if (line != NULL)
*line = eline;
BIO_snprintf(btmp, sizeof(btmp), "%ld", eline);
ERR_add_error_data(2, "line ", btmp);
if (h != conf->data) {
CONF_free(conf->data);
conf->data = NULL;
}
if (v != NULL) {
OPENSSL_free(v->name);
OPENSSL_free(v->value);
OPENSSL_free(v);
}
return 0;
}
static void clear_comments(CONF *conf, char *p)
{
for (;;) {
if (IS_FCOMMENT(conf, *p)) {
*p = '\0';
return;
}
if (!IS_WS(conf, *p)) {
break;
}
p++;
}
for (;;) {
if (IS_COMMENT(conf, *p)) {
*p = '\0';
return;
}
if (IS_DQUOTE(conf, *p)) {
p = scan_dquote(conf, p);
continue;
}
if (IS_QUOTE(conf, *p)) {
p = scan_quote(conf, p);
continue;
}
if (IS_ESC(conf, *p)) {
p = scan_esc(conf, p);
continue;
}
if (IS_EOF(conf, *p))
return;
else
p++;
}
}
static int str_copy(CONF *conf, char *section, char **pto, char *from)
{
int q, r, rr = 0, to = 0, len = 0;
char *s, *e, *rp, *p, *rrp, *np, *cp, v;
BUF_MEM *buf;
if ((buf = BUF_MEM_new()) == NULL)
return 0;
len = strlen(from) + 1;
if (!BUF_MEM_grow(buf, len))
goto err;
for (;;) {
if (IS_QUOTE(conf, *from)) {
q = *from;
from++;
while (!IS_EOF(conf, *from) && (*from != q)) {
if (IS_ESC(conf, *from)) {
from++;
if (IS_EOF(conf, *from))
break;
}
buf->data[to++] = *(from++);
}
if (*from == q)
from++;
} else if (IS_DQUOTE(conf, *from)) {
q = *from;
from++;
while (!IS_EOF(conf, *from)) {
if (*from == q) {
if (*(from + 1) == q) {
from++;
} else {
break;
}
}
buf->data[to++] = *(from++);
}
if (*from == q)
from++;
} else if (IS_ESC(conf, *from)) {
from++;
v = *(from++);
if (IS_EOF(conf, v))
break;
else if (v == 'r')
v = '\r';
else if (v == 'n')
v = '\n';
else if (v == 'b')
v = '\b';
else if (v == 't')
v = '\t';
buf->data[to++] = v;
} else if (IS_EOF(conf, *from))
break;
else if (*from == '$'
&& (!conf->flag_dollarid
|| from[1] == '{'
|| from[1] == '(')) {
size_t newsize;
/* try to expand it */
rrp = NULL;
s = &(from[1]);
if (*s == '{')
q = '}';
else if (*s == '(')
q = ')';
else
q = 0;
if (q)
s++;
cp = section;
e = np = s;
while (IS_ALNUM(conf, *e)
|| (conf->flag_dollarid && IS_DOLLAR(conf, *e)))
e++;
if ((e[0] == ':') && (e[1] == ':')) {
cp = np;
rrp = e;
rr = *e;
*rrp = '\0';
e += 2;
np = e;
while (IS_ALNUM(conf, *e)
|| (conf->flag_dollarid && IS_DOLLAR(conf, *e)))
e++;
}
r = *e;
*e = '\0';
rp = e;
if (q) {
if (r != q) {
ERR_raise(ERR_LIB_CONF, CONF_R_NO_CLOSE_BRACE);
goto err;
}
e++;
}
/*-
* So at this point we have
* np which is the start of the name string which is
* '\0' terminated.
* cp which is the start of the section string which is
* '\0' terminated.
* e is the 'next point after'.
* r and rr are the chars replaced by the '\0'
* rp and rrp is where 'r' and 'rr' came from.
*/
p = _CONF_get_string(conf, cp, np);
if (rrp != NULL)
*rrp = rr;
*rp = r;
if (p == NULL) {
ERR_raise(ERR_LIB_CONF, CONF_R_VARIABLE_HAS_NO_VALUE);
goto err;
}
newsize = strlen(p) + buf->length - (e - from);
if (newsize > MAX_CONF_VALUE_LENGTH) {
ERR_raise(ERR_LIB_CONF, CONF_R_VARIABLE_EXPANSION_TOO_LONG);
goto err;
}
if (!BUF_MEM_grow_clean(buf, newsize)) {
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
while (*p)
buf->data[to++] = *(p++);
/*
* Since we change the pointer 'from', we also have to change the
* perceived length of the string it points at. /RL
*/
len -= e - from;
from = e;
/*
* In case there were no braces or parenthesis around the
* variable reference, we have to put back the character that was
* replaced with a '\0'. /RL
*/
*rp = r;
} else
buf->data[to++] = *(from++);
}
buf->data[to] = '\0';
OPENSSL_free(*pto);
*pto = buf->data;
OPENSSL_free(buf);
return 1;
err:
BUF_MEM_free(buf);
return 0;
}
#ifndef OPENSSL_NO_POSIX_IO
/*
* Check whether included path is a directory.
* Returns next BIO to process and in case of a directory
* also an opened directory context and the include path.
*/
static BIO *process_include(char *include, OPENSSL_DIR_CTX **dirctx,
char **dirpath)
{
struct stat st;
BIO *next;
if (stat(include, &st) < 0) {
ERR_raise_data(ERR_LIB_SYS, errno, "calling stat(%s)", include);
/* missing include file is not fatal error */
return NULL;
}
if (S_ISDIR(st.st_mode)) {
if (*dirctx != NULL) {
ERR_raise_data(ERR_LIB_CONF, CONF_R_RECURSIVE_DIRECTORY_INCLUDE,
"%s", include);
return NULL;
}
/* a directory, load its contents */
if ((next = get_next_file(include, dirctx)) != NULL)
*dirpath = include;
return next;
}
next = BIO_new_file(include, "r");
return next;
}
/*
* Get next file from the directory path.
* Returns BIO of the next file to read and updates dirctx.
*/
static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx)
{
const char *filename;
size_t pathlen;
pathlen = strlen(path);
while ((filename = OPENSSL_DIR_read(dirctx, path)) != NULL) {
size_t namelen;
namelen = strlen(filename);
if ((namelen > 5
&& OPENSSL_strcasecmp(filename + namelen - 5, ".conf") == 0)
|| (namelen > 4
&& OPENSSL_strcasecmp(filename + namelen - 4, ".cnf") == 0)) {
size_t newlen;
char *newpath;
BIO *bio;
newlen = pathlen + namelen + 2;
newpath = OPENSSL_zalloc(newlen);
if (newpath == NULL) {
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
break;
}
#ifdef OPENSSL_SYS_VMS
/*
* If the given path isn't clear VMS syntax,
* we treat it as on Unix.
*/
if (path[pathlen - 1] == ']'
|| path[pathlen - 1] == '>'
|| path[pathlen - 1] == ':') {
/* Clear VMS directory syntax, just copy as is */
OPENSSL_strlcpy(newpath, path, newlen);
}
#endif
if (newpath[0] == '\0') {
OPENSSL_strlcpy(newpath, path, newlen);
OPENSSL_strlcat(newpath, "/", newlen);
}
OPENSSL_strlcat(newpath, filename, newlen);
bio = BIO_new_file(newpath, "r");
OPENSSL_free(newpath);
/* Errors when opening files are non-fatal. */
if (bio != NULL)
return bio;
}
}
OPENSSL_DIR_end(dirctx);
*dirctx = NULL;
return NULL;
}
#endif
static int is_keytype(const CONF *conf, char c, unsigned short type)
{
const unsigned short * keytypes = (const unsigned short *) conf->meth_data;
unsigned char key = (unsigned char)c;
#ifdef CHARSET_EBCDIC
# if CHAR_BIT > 8
if (key > 255) {
/* key is out of range for os_toascii table */
return 0;
}
# endif
/* convert key from ebcdic to ascii */
key = os_toascii[key];
#endif
if (key > 127) {
/* key is not a seven bit ascii character */
return 0;
}
return (keytypes[key] & type) ? 1 : 0;
}
static char *eat_ws(CONF *conf, char *p)
{
while (IS_WS(conf, *p) && (!IS_EOF(conf, *p)))
p++;
return p;
}
static void trim_ws(CONF *conf, char *start)
{
char *p = start;
while (!IS_EOF(conf, *p))
p++;
p--;
while ((p >= start) && IS_WS(conf, *p))
p--;
p++;
*p = '\0';
}
static char *eat_alpha_numeric(CONF *conf, char *p)
{
for (;;) {
if (IS_ESC(conf, *p)) {
p = scan_esc(conf, p);
continue;
}
if (!(IS_ALNUM_PUNCT(conf, *p)
|| (conf->flag_dollarid && IS_DOLLAR(conf, *p))))
return p;
p++;
}
}
static char *scan_quote(CONF *conf, char *p)
{
int q = *p;
p++;
while (!(IS_EOF(conf, *p)) && (*p != q)) {
if (IS_ESC(conf, *p)) {
p++;
if (IS_EOF(conf, *p))
return p;
}
p++;
}
if (*p == q)
p++;
return p;
}
static char *scan_dquote(CONF *conf, char *p)
{
int q = *p;
p++;
while (!(IS_EOF(conf, *p))) {
if (*p == q) {
if (*(p + 1) == q) {
p++;
} else {
break;
}
}
p++;
}
if (*p == q)
p++;
return p;
}
static void dump_value_doall_arg(const CONF_VALUE *a, BIO *out)
{
if (a->name)
BIO_printf(out, "[%s] %s=%s\n", a->section, a->name, a->value);
else
BIO_printf(out, "[[%s]]\n", a->section);
}
IMPLEMENT_LHASH_DOALL_ARG_CONST(CONF_VALUE, BIO);
static int def_dump(const CONF *conf, BIO *out)
{
lh_CONF_VALUE_doall_BIO(conf->data, dump_value_doall_arg, out);
return 1;
}
static int def_is_number(const CONF *conf, char c)
{
return IS_NUMBER(conf, c);
}
static int def_to_int(const CONF *conf, char c)
{
return c - '0';
}
diff --git a/crypto/dsa/dsa_backend.c b/crypto/dsa/dsa_backend.c
index f9a71bdc9e0b..389df304bdce 100644
--- a/crypto/dsa/dsa_backend.c
+++ b/crypto/dsa/dsa_backend.c
@@ -1,192 +1,195 @@
/*
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/*
* DSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <openssl/core_names.h>
#include <openssl/err.h>
#ifndef FIPS_MODULE
# include <openssl/x509.h>
#endif
#include "crypto/dsa.h"
#include "dsa_local.h"
/*
* 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_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[],
int include_private)
{
const OSSL_PARAM *param_priv_key = NULL, *param_pub_key;
BIGNUM *priv_key = NULL, *pub_key = NULL;
if (dsa == NULL)
return 0;
if (include_private) {
param_priv_key =
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
}
param_pub_key =
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
/* It's ok if neither half is present */
if (param_priv_key == NULL && param_pub_key == NULL)
return 1;
if (param_pub_key != NULL && !OSSL_PARAM_get_BN(param_pub_key, &pub_key))
goto err;
if (param_priv_key != NULL && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
goto err;
if (!DSA_set0_key(dsa, pub_key, priv_key))
goto err;
return 1;
err:
BN_clear_free(priv_key);
BN_free(pub_key);
return 0;
}
int ossl_dsa_is_foreign(const DSA *dsa)
{
#ifndef FIPS_MODULE
if (dsa->engine != NULL || DSA_get_method((DSA *)dsa) != DSA_OpenSSL())
return 1;
#endif
return 0;
}
static ossl_inline int dsa_bn_dup_check(BIGNUM **out, const BIGNUM *f)
{
if (f != NULL && (*out = BN_dup(f)) == NULL)
return 0;
return 1;
}
DSA *ossl_dsa_dup(const DSA *dsa, int selection)
{
DSA *dupkey = NULL;
/* Do not try to duplicate foreign DSA keys */
if (ossl_dsa_is_foreign(dsa))
return NULL;
if ((dupkey = ossl_dsa_new(dsa->libctx)) == NULL)
return NULL;
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0
&& !ossl_ffc_params_copy(&dupkey->params, &dsa->params))
goto err;
dupkey->flags = dsa->flags;
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0
&& ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0
|| !dsa_bn_dup_check(&dupkey->pub_key, dsa->pub_key)))
goto err;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
&& ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0
|| !dsa_bn_dup_check(&dupkey->priv_key, dsa->priv_key)))
goto err;
#ifndef FIPS_MODULE
if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DSA,
&dupkey->ex_data, &dsa->ex_data))
goto err;
#endif
return dupkey;
err:
DSA_free(dupkey);
return NULL;
}
#ifndef FIPS_MODULE
DSA *ossl_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
OSSL_LIB_CTX *libctx, const char *propq)
{
const unsigned char *p, *pm;
int pklen, pmlen;
int ptype;
const void *pval;
const ASN1_STRING *pstr;
const X509_ALGOR *palg;
ASN1_INTEGER *privkey = NULL;
const BIGNUM *dsa_p, *dsa_g;
BIGNUM *dsa_pubkey = NULL, *dsa_privkey = NULL;
BN_CTX *ctx = NULL;
DSA *dsa = NULL;
if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf))
return 0;
X509_ALGOR_get0(NULL, &ptype, &pval, palg);
if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)
goto decerr;
if (privkey->type == V_ASN1_NEG_INTEGER || ptype != V_ASN1_SEQUENCE)
goto decerr;
pstr = pval;
pm = pstr->data;
pmlen = pstr->length;
if ((dsa = d2i_DSAparams(NULL, &pm, pmlen)) == NULL)
goto decerr;
/* We have parameters now set private key */
if ((dsa_privkey = BN_secure_new()) == NULL
|| !ASN1_INTEGER_to_BN(privkey, dsa_privkey)) {
ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR);
goto dsaerr;
}
/* Calculate public key */
if ((dsa_pubkey = BN_new()) == NULL) {
ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
goto dsaerr;
}
if ((ctx = BN_CTX_new()) == NULL) {
ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
goto dsaerr;
}
dsa_p = DSA_get0_p(dsa);
dsa_g = DSA_get0_g(dsa);
BN_set_flags(dsa_privkey, BN_FLG_CONSTTIME);
if (!BN_mod_exp(dsa_pubkey, dsa_g, dsa_privkey, dsa_p, ctx)) {
ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR);
goto dsaerr;
}
- DSA_set0_key(dsa, dsa_pubkey, dsa_privkey);
+ if (!DSA_set0_key(dsa, dsa_pubkey, dsa_privkey)) {
+ ERR_raise(ERR_LIB_DSA, ERR_R_INTERNAL_ERROR);
+ goto dsaerr;
+ }
goto done;
decerr:
ERR_raise(ERR_LIB_DSA, DSA_R_DECODE_ERROR);
dsaerr:
BN_free(dsa_privkey);
BN_free(dsa_pubkey);
DSA_free(dsa);
dsa = NULL;
done:
BN_CTX_free(ctx);
ASN1_STRING_clear_free(privkey);
return dsa;
}
#endif
diff --git a/crypto/dsa/dsa_err.c b/crypto/dsa/dsa_err.c
index 5685d5e83eb3..a92ca6166477 100644
--- a/crypto/dsa/dsa_err.c
+++ b/crypto/dsa/dsa_err.c
@@ -1,54 +1,55 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <openssl/err.h>
#include <openssl/dsaerr.h>
#include "crypto/dsaerr.h"
#ifndef OPENSSL_NO_DSA
# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA DSA_str_reasons[] = {
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BAD_FFC_PARAMETERS), "bad ffc parameters"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BAD_Q_VALUE), "bad q value"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BN_DECODE_ERROR), "bn decode error"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BN_ERROR), "bn error"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_DECODE_ERROR), "decode error"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_INVALID_DIGEST_TYPE),
"invalid digest type"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_INVALID_PARAMETERS), "invalid parameters"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_MISSING_PARAMETERS), "missing parameters"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_MISSING_PRIVATE_KEY),
"missing private key"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_MODULUS_TOO_LARGE), "modulus too large"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_NO_PARAMETERS_SET), "no parameters set"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_PARAMETER_ENCODING_ERROR),
"parameter encoding error"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_P_NOT_PRIME), "p not prime"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_Q_NOT_PRIME), "q not prime"},
{ERR_PACK(ERR_LIB_DSA, 0, DSA_R_SEED_LEN_SMALL),
"seed_len is less than the length of q"},
+ {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_TOO_MANY_RETRIES), "too many retries"},
{0, NULL}
};
# endif
int ossl_err_load_DSA_strings(void)
{
# ifndef OPENSSL_NO_ERR
if (ERR_reason_error_string(DSA_str_reasons[0].error) == NULL)
ERR_load_strings_const(DSA_str_reasons);
# endif
return 1;
}
#else
NON_EMPTY_TRANSLATION_UNIT
#endif
diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c
index 86d89f4c724f..62f7c70149f4 100644
--- a/crypto/dsa/dsa_ossl.c
+++ b/crypto/dsa/dsa_ossl.c
@@ -1,466 +1,481 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/*
* DSA 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 "crypto/bn.h"
#include <openssl/bn.h>
#include <openssl/sha.h>
#include "dsa_local.h"
#include <openssl/asn1.h>
+#define MIN_DSA_SIGN_QBITS 128
+#define MAX_DSA_SIGN_RETRIES 8
+
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp);
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp, const unsigned char *dgst, int dlen);
static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
DSA_SIG *sig, DSA *dsa);
static int dsa_init(DSA *dsa);
static int dsa_finish(DSA *dsa);
static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q,
BN_CTX *ctx);
static DSA_METHOD openssl_dsa_meth = {
"OpenSSL DSA method",
dsa_do_sign,
dsa_sign_setup_no_digest,
dsa_do_verify,
NULL, /* dsa_mod_exp, */
NULL, /* dsa_bn_mod_exp, */
dsa_init,
dsa_finish,
DSA_FLAG_FIPS_METHOD,
NULL,
NULL,
NULL
};
static const DSA_METHOD *default_DSA_method = &openssl_dsa_meth;
#ifndef FIPS_MODULE
void DSA_set_default_method(const DSA_METHOD *meth)
{
default_DSA_method = meth;
}
#endif /* FIPS_MODULE */
const DSA_METHOD *DSA_get_default_method(void)
{
return default_DSA_method;
}
const DSA_METHOD *DSA_OpenSSL(void)
{
return &openssl_dsa_meth;
}
DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa)
{
BIGNUM *kinv = NULL;
BIGNUM *m, *blind, *blindm, *tmp;
BN_CTX *ctx = NULL;
int reason = ERR_R_BN_LIB;
DSA_SIG *ret = NULL;
int rv = 0;
+ int retries = 0;
if (dsa->params.p == NULL
|| dsa->params.q == NULL
|| dsa->params.g == NULL) {
reason = DSA_R_MISSING_PARAMETERS;
goto err;
}
if (dsa->priv_key == NULL) {
reason = DSA_R_MISSING_PRIVATE_KEY;
goto err;
}
ret = DSA_SIG_new();
if (ret == NULL)
goto err;
ret->r = BN_new();
ret->s = BN_new();
if (ret->r == NULL || ret->s == NULL)
goto err;
ctx = BN_CTX_new_ex(dsa->libctx);
if (ctx == NULL)
goto err;
m = BN_CTX_get(ctx);
blind = BN_CTX_get(ctx);
blindm = BN_CTX_get(ctx);
tmp = BN_CTX_get(ctx);
if (tmp == NULL)
goto err;
redo:
if (!dsa_sign_setup(dsa, ctx, &kinv, &ret->r, dgst, dlen))
goto err;
if (dlen > BN_num_bytes(dsa->params.q))
/*
* if the digest length is greater than the size of q use the
* BN_num_bits(dsa->q) leftmost bits of the digest, see fips 186-3,
* 4.2
*/
dlen = BN_num_bytes(dsa->params.q);
if (BN_bin2bn(dgst, dlen, m) == NULL)
goto err;
/*
* The normal signature calculation is:
*
* s := k^-1 * (m + r * priv_key) mod q
*
* We will blind this to protect against side channel attacks
*
* s := blind^-1 * k^-1 * (blind * m + blind * r * priv_key) mod q
*/
- /* Generate a blinding value */
+ /*
+ * Generate a blinding value
+ * The size of q is tested in dsa_sign_setup() so there should not be an infinite loop here.
+ */
do {
if (!BN_priv_rand_ex(blind, BN_num_bits(dsa->params.q) - 1,
BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx))
goto err;
} while (BN_is_zero(blind));
BN_set_flags(blind, BN_FLG_CONSTTIME);
BN_set_flags(blindm, BN_FLG_CONSTTIME);
BN_set_flags(tmp, BN_FLG_CONSTTIME);
/* tmp := blind * priv_key * r mod q */
if (!BN_mod_mul(tmp, blind, dsa->priv_key, dsa->params.q, ctx))
goto err;
if (!BN_mod_mul(tmp, tmp, ret->r, dsa->params.q, ctx))
goto err;
/* blindm := blind * m mod q */
if (!BN_mod_mul(blindm, blind, m, dsa->params.q, ctx))
goto err;
/* s : = (blind * priv_key * r) + (blind * m) mod q */
if (!BN_mod_add_quick(ret->s, tmp, blindm, dsa->params.q))
goto err;
/* s := s * k^-1 mod q */
if (!BN_mod_mul(ret->s, ret->s, kinv, dsa->params.q, ctx))
goto err;
/* s:= s * blind^-1 mod q */
if (BN_mod_inverse(blind, blind, dsa->params.q, ctx) == NULL)
goto err;
if (!BN_mod_mul(ret->s, ret->s, blind, dsa->params.q, ctx))
goto err;
/*
- * Redo if r or s is zero as required by FIPS 186-3: this is very
- * unlikely.
+ * Redo if r or s is zero as required by FIPS 186-4: Section 4.6
+ * This is very unlikely.
+ * Limit the retries so there is no possibility of an infinite
+ * loop for bad domain parameter values.
*/
- if (BN_is_zero(ret->r) || BN_is_zero(ret->s))
+ if (BN_is_zero(ret->r) || BN_is_zero(ret->s)) {
+ if (retries++ > MAX_DSA_SIGN_RETRIES) {
+ reason = DSA_R_TOO_MANY_RETRIES;
+ goto err;
+ }
goto redo;
-
+ }
rv = 1;
-
err:
if (rv == 0) {
ERR_raise(ERR_LIB_DSA, reason);
DSA_SIG_free(ret);
ret = NULL;
}
BN_CTX_free(ctx);
BN_clear_free(kinv);
return ret;
}
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
{
return ossl_dsa_do_sign_int(dgst, dlen, dsa);
}
static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in,
BIGNUM **kinvp, BIGNUM **rp)
{
return dsa_sign_setup(dsa, ctx_in, kinvp, rp, NULL, 0);
}
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
BIGNUM **kinvp, BIGNUM **rp,
const unsigned char *dgst, int dlen)
{
BN_CTX *ctx = NULL;
BIGNUM *k, *kinv = NULL, *r = *rp;
BIGNUM *l;
int ret = 0;
int q_bits, q_words;
if (!dsa->params.p || !dsa->params.q || !dsa->params.g) {
ERR_raise(ERR_LIB_DSA, DSA_R_MISSING_PARAMETERS);
return 0;
}
/* Reject obviously invalid parameters */
if (BN_is_zero(dsa->params.p)
|| BN_is_zero(dsa->params.q)
- || BN_is_zero(dsa->params.g)) {
+ || BN_is_zero(dsa->params.g)
+ || BN_is_negative(dsa->params.p)
+ || BN_is_negative(dsa->params.q)
+ || BN_is_negative(dsa->params.g)) {
ERR_raise(ERR_LIB_DSA, DSA_R_INVALID_PARAMETERS);
return 0;
}
if (dsa->priv_key == NULL) {
ERR_raise(ERR_LIB_DSA, DSA_R_MISSING_PRIVATE_KEY);
return 0;
}
-
k = BN_new();
l = BN_new();
if (k == NULL || l == NULL)
goto err;
if (ctx_in == NULL) {
/* if you don't pass in ctx_in you get a default libctx */
if ((ctx = BN_CTX_new_ex(NULL)) == NULL)
goto err;
} else
ctx = ctx_in;
/* Preallocate space */
q_bits = BN_num_bits(dsa->params.q);
q_words = bn_get_top(dsa->params.q);
- if (!bn_wexpand(k, q_words + 2)
+ if (q_bits < MIN_DSA_SIGN_QBITS
+ || !bn_wexpand(k, q_words + 2)
|| !bn_wexpand(l, q_words + 2))
goto err;
/* Get random k */
do {
if (dgst != NULL) {
/*
* We calculate k from SHA512(private_key + H(message) + random).
* This protects the private key from a weak PRNG.
*/
if (!BN_generate_dsa_nonce(k, dsa->params.q, dsa->priv_key, dgst,
dlen, ctx))
goto err;
} else if (!BN_priv_rand_range_ex(k, dsa->params.q, 0, ctx))
goto err;
} while (BN_is_zero(k));
BN_set_flags(k, BN_FLG_CONSTTIME);
BN_set_flags(l, BN_FLG_CONSTTIME);
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p,
dsa->lock, dsa->params.p, ctx))
goto err;
}
/* Compute r = (g^k mod p) mod q */
/*
* We do not want timing information to leak the length of k, so we
* compute G^k using an equivalent scalar of fixed bit-length.
*
* We unconditionally perform both of these additions to prevent a
* small timing information leakage. We then choose the sum that is
* one bit longer than the modulus.
*
* There are some concerns about the efficacy of doing this. More
* specifically refer to the discussion starting with:
* https://github.com/openssl/openssl/pull/7486#discussion_r228323705
* The fix is to rework BN so these gymnastics aren't required.
*/
if (!BN_add(l, k, dsa->params.q)
|| !BN_add(k, l, dsa->params.q))
goto err;
BN_consttime_swap(BN_is_bit_set(l, q_bits), k, l, q_words + 2);
if ((dsa)->meth->bn_mod_exp != NULL) {
if (!dsa->meth->bn_mod_exp(dsa, r, dsa->params.g, k, dsa->params.p,
ctx, dsa->method_mont_p))
goto err;
} else {
if (!BN_mod_exp_mont(r, dsa->params.g, k, dsa->params.p, ctx,
dsa->method_mont_p))
goto err;
}
if (!BN_mod(r, r, dsa->params.q, ctx))
goto err;
/* Compute part of 's = inv(k) (m + xr) mod q' */
if ((kinv = dsa_mod_inverse_fermat(k, dsa->params.q, ctx)) == NULL)
goto err;
BN_clear_free(*kinvp);
*kinvp = kinv;
kinv = NULL;
ret = 1;
err:
if (!ret)
ERR_raise(ERR_LIB_DSA, ERR_R_BN_LIB);
if (ctx != ctx_in)
BN_CTX_free(ctx);
BN_clear_free(k);
BN_clear_free(l);
return ret;
}
static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
DSA_SIG *sig, DSA *dsa)
{
BN_CTX *ctx;
BIGNUM *u1, *u2, *t1;
BN_MONT_CTX *mont = NULL;
const BIGNUM *r, *s;
int ret = -1, i;
if (dsa->params.p == NULL
|| dsa->params.q == NULL
|| dsa->params.g == NULL) {
ERR_raise(ERR_LIB_DSA, DSA_R_MISSING_PARAMETERS);
return -1;
}
i = BN_num_bits(dsa->params.q);
/* fips 186-3 allows only different sizes for q */
if (i != 160 && i != 224 && i != 256) {
ERR_raise(ERR_LIB_DSA, DSA_R_BAD_Q_VALUE);
return -1;
}
if (BN_num_bits(dsa->params.p) > OPENSSL_DSA_MAX_MODULUS_BITS) {
ERR_raise(ERR_LIB_DSA, DSA_R_MODULUS_TOO_LARGE);
return -1;
}
u1 = BN_new();
u2 = BN_new();
t1 = BN_new();
ctx = BN_CTX_new_ex(NULL); /* verify does not need a libctx */
if (u1 == NULL || u2 == NULL || t1 == NULL || ctx == NULL)
goto err;
DSA_SIG_get0(sig, &r, &s);
if (BN_is_zero(r) || BN_is_negative(r) ||
BN_ucmp(r, dsa->params.q) >= 0) {
ret = 0;
goto err;
}
if (BN_is_zero(s) || BN_is_negative(s) ||
BN_ucmp(s, dsa->params.q) >= 0) {
ret = 0;
goto err;
}
/*
* Calculate W = inv(S) mod Q save W in u2
*/
if ((BN_mod_inverse(u2, s, dsa->params.q, ctx)) == NULL)
goto err;
/* save M in u1 */
if (dgst_len > (i >> 3))
/*
* if the digest length is greater than the size of q use the
* BN_num_bits(dsa->q) leftmost bits of the digest, see fips 186-3,
* 4.2
*/
dgst_len = (i >> 3);
if (BN_bin2bn(dgst, dgst_len, u1) == NULL)
goto err;
/* u1 = M * w mod q */
if (!BN_mod_mul(u1, u1, u2, dsa->params.q, ctx))
goto err;
/* u2 = r * w mod q */
if (!BN_mod_mul(u2, r, u2, dsa->params.q, ctx))
goto err;
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
mont = BN_MONT_CTX_set_locked(&dsa->method_mont_p,
dsa->lock, dsa->params.p, ctx);
if (!mont)
goto err;
}
if (dsa->meth->dsa_mod_exp != NULL) {
if (!dsa->meth->dsa_mod_exp(dsa, t1, dsa->params.g, u1, dsa->pub_key, u2,
dsa->params.p, ctx, mont))
goto err;
} else {
if (!BN_mod_exp2_mont(t1, dsa->params.g, u1, dsa->pub_key, u2,
dsa->params.p, ctx, mont))
goto err;
}
/* let u1 = u1 mod q */
if (!BN_mod(u1, t1, dsa->params.q, ctx))
goto err;
/*
* V is now in u1. If the signature is correct, it will be equal to R.
*/
ret = (BN_ucmp(u1, r) == 0);
err:
if (ret < 0)
ERR_raise(ERR_LIB_DSA, ERR_R_BN_LIB);
BN_CTX_free(ctx);
BN_free(u1);
BN_free(u2);
BN_free(t1);
return ret;
}
static int dsa_init(DSA *dsa)
{
dsa->flags |= DSA_FLAG_CACHE_MONT_P;
ossl_ffc_params_init(&dsa->params);
dsa->dirty_cnt++;
return 1;
}
static int dsa_finish(DSA *dsa)
{
BN_MONT_CTX_free(dsa->method_mont_p);
return 1;
}
/*
* Compute the inverse of k modulo q.
* Since q is prime, Fermat's Little Theorem applies, which reduces this to
* mod-exp operation. Both the exponent and modulus are public information
* so a mod-exp that doesn't leak the base is sufficient. A newly allocated
* BIGNUM is returned which the caller must free.
*/
static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q,
BN_CTX *ctx)
{
BIGNUM *res = NULL;
BIGNUM *r, *e;
if ((r = BN_new()) == NULL)
return NULL;
BN_CTX_start(ctx);
if ((e = BN_CTX_get(ctx)) != NULL
&& BN_set_word(r, 2)
&& BN_sub(e, q, r)
&& BN_mod_exp_mont(r, k, e, q, ctx, NULL))
res = r;
else
BN_free(r);
BN_CTX_end(ctx);
return res;
}
diff --git a/crypto/dsa/dsa_sign.c b/crypto/dsa/dsa_sign.c
index 21b0cbd5fbef..ddfbfa18af15 100644
--- a/crypto/dsa/dsa_sign.c
+++ b/crypto/dsa/dsa_sign.c
@@ -1,209 +1,209 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/*
* DSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <openssl/bn.h>
#include "internal/cryptlib.h"
#include "dsa_local.h"
#include "crypto/asn1_dsa.h"
#include "crypto/dsa.h"
DSA_SIG *DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
{
return dsa->meth->dsa_do_sign(dgst, dlen, dsa);
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
{
return dsa->meth->dsa_sign_setup(dsa, ctx_in, kinvp, rp);
}
#endif
DSA_SIG *DSA_SIG_new(void)
{
DSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig));
if (sig == NULL)
ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
return sig;
}
void DSA_SIG_free(DSA_SIG *sig)
{
if (sig == NULL)
return;
BN_clear_free(sig->r);
BN_clear_free(sig->s);
OPENSSL_free(sig);
}
DSA_SIG *d2i_DSA_SIG(DSA_SIG **psig, const unsigned char **ppin, long len)
{
DSA_SIG *sig;
if (len < 0)
return NULL;
if (psig != NULL && *psig != NULL) {
sig = *psig;
} else {
sig = DSA_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)
DSA_SIG_free(sig);
return NULL;
}
if (psig != NULL && *psig == NULL)
*psig = sig;
return sig;
}
int i2d_DSA_SIG(const DSA_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;
}
int DSA_size(const DSA *dsa)
{
int ret = -1;
DSA_SIG sig;
if (dsa->params.q != NULL) {
sig.r = sig.s = dsa->params.q;
ret = i2d_DSA_SIG(&sig, NULL);
if (ret < 0)
ret = 0;
}
return ret;
}
void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
{
if (pr != NULL)
*pr = sig->r;
if (ps != NULL)
*ps = sig->s;
}
int DSA_SIG_set0(DSA_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 ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen, DSA *dsa)
{
DSA_SIG *s;
/* legacy case uses the method table */
if (dsa->libctx == NULL || dsa->meth != DSA_get_default_method())
s = DSA_do_sign(dgst, dlen, dsa);
else
s = ossl_dsa_do_sign_int(dgst, dlen, dsa);
if (s == NULL) {
*siglen = 0;
return 0;
}
- *siglen = i2d_DSA_SIG(s, &sig);
+ *siglen = i2d_DSA_SIG(s, sig != NULL ? &sig : NULL);
DSA_SIG_free(s);
return 1;
}
int DSA_sign(int type, const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen, DSA *dsa)
{
return ossl_dsa_sign_int(type, dgst, dlen, sig, siglen, dsa);
}
/* data has already been hashed (probably with SHA or SHA-1). */
/*-
* returns
* 1: correct signature
* 0: incorrect signature
* -1: error
*/
int DSA_verify(int type, const unsigned char *dgst, int dgst_len,
const unsigned char *sigbuf, int siglen, DSA *dsa)
{
DSA_SIG *s;
const unsigned char *p = sigbuf;
unsigned char *der = NULL;
int derlen = -1;
int ret = -1;
s = DSA_SIG_new();
if (s == NULL)
return ret;
if (d2i_DSA_SIG(&s, &p, siglen) == NULL)
goto err;
/* Ensure signature uses DER and doesn't have trailing garbage */
derlen = i2d_DSA_SIG(s, &der);
if (derlen != siglen || memcmp(sigbuf, der, derlen))
goto err;
ret = DSA_do_verify(dgst, dgst_len, s, dsa);
err:
OPENSSL_clear_free(der, derlen);
DSA_SIG_free(s);
return ret;
}
diff --git a/crypto/ec/asm/ecp_nistp521-ppc64.pl b/crypto/ec/asm/ecp_nistp521-ppc64.pl
index 4260e24a1f57..cf3bc79085f8 100755
--- a/crypto/ec/asm/ecp_nistp521-ppc64.pl
+++ b/crypto/ec/asm/ecp_nistp521-ppc64.pl
@@ -1,435 +1,436 @@
#! /usr/bin/env perl
-# Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2021-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
#
# ====================================================================
# Written by Amitay Isaacs <amitay@ozlabs.org> and Martin Schwenke
# <martin@meltin.net> for the OpenSSL project.
# ====================================================================
#
# p521 lower-level primitives for PPC64 using vector instructions.
#
use strict;
use warnings;
my $flavour = shift;
my $output = "";
while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
if (!$output) {
$output = "-";
}
my ($xlate, $dir);
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
open OUT,"| \"$^X\" $xlate $flavour $output";
*STDOUT=*OUT;
my $code = "";
my ($sp, $outp, $savelr, $savesp) = ("r1", "r3", "r10", "r12");
my $vzero = "v32";
sub startproc($)
{
my ($name) = @_;
$code.=<<___;
.globl ${name}
.align 5
${name}:
___
}
sub endproc($)
{
my ($name) = @_;
$code.=<<___;
blr
.size ${name},.-${name}
___
}
sub push_vrs($$)
{
my ($min, $max) = @_;
my $count = $max - $min + 1;
$code.=<<___;
mr $savesp,$sp
stdu $sp,-16*`$count+1`($sp)
___
for (my $i = $min; $i <= $max; $i++) {
my $mult = $max - $i + 1;
$code.=<<___;
stxv $i,-16*$mult($savesp)
___
}
$code.=<<___;
___
}
sub pop_vrs($$)
{
my ($min, $max) = @_;
$code.=<<___;
ld $savesp,0($sp)
___
for (my $i = $min; $i <= $max; $i++) {
my $mult = $max - $i + 1;
$code.=<<___;
lxv $i,-16*$mult($savesp)
___
}
$code.=<<___;
mr $sp,$savesp
___
}
sub load_vrs($$)
{
my ($pointer, $reg_list) = @_;
for (my $i = 0; $i <= 8; $i++) {
my $offset = $i * 8;
$code.=<<___;
lxsd $reg_list->[$i],$offset($pointer)
___
}
$code.=<<___;
___
}
sub store_vrs($$)
{
my ($pointer, $reg_list) = @_;
for (my $i = 0; $i <= 8; $i++) {
my $offset = $i * 16;
$code.=<<___;
stxv $reg_list->[$i],$offset($pointer)
___
}
$code.=<<___;
___
}
$code.=<<___;
+.machine "any"
.text
___
{
# mul/square common
my ($t1, $t2, $t3, $t4) = ("v33", "v34", "v44", "v54");
my ($zero, $one) = ("r8", "r9");
my @out = map("v$_",(55..63));
{
#
# p521_felem_mul
#
my ($in1p, $in2p) = ("r4", "r5");
my @in1 = map("v$_",(45..53));
my @in2 = map("v$_",(35..43));
startproc("p521_felem_mul");
push_vrs(52, 63);
$code.=<<___;
vspltisw $vzero,0
___
load_vrs($in1p, \@in1);
load_vrs($in2p, \@in2);
$code.=<<___;
vmsumudm $out[0],$in1[0],$in2[0],$vzero
xxpermdi $t1,$in1[0],$in1[1],0b00
xxpermdi $t2,$in2[1],$in2[0],0b00
vmsumudm $out[1],$t1,$t2,$vzero
xxpermdi $t2,$in2[2],$in2[1],0b00
vmsumudm $out[2],$t1,$t2,$vzero
vmsumudm $out[2],$in1[2],$in2[0],$out[2]
xxpermdi $t2,$in2[3],$in2[2],0b00
vmsumudm $out[3],$t1,$t2,$vzero
xxpermdi $t3,$in1[2],$in1[3],0b00
xxpermdi $t4,$in2[1],$in2[0],0b00
vmsumudm $out[3],$t3,$t4,$out[3]
xxpermdi $t2,$in2[4],$in2[3],0b00
vmsumudm $out[4],$t1,$t2,$vzero
xxpermdi $t4,$in2[2],$in2[1],0b00
vmsumudm $out[4],$t3,$t4,$out[4]
vmsumudm $out[4],$in1[4],$in2[0],$out[4]
xxpermdi $t2,$in2[5],$in2[4],0b00
vmsumudm $out[5],$t1,$t2,$vzero
xxpermdi $t4,$in2[3],$in2[2],0b00
vmsumudm $out[5],$t3,$t4,$out[5]
xxpermdi $t2,$in2[6],$in2[5],0b00
vmsumudm $out[6],$t1,$t2,$vzero
xxpermdi $t4,$in2[4],$in2[3],0b00
vmsumudm $out[6],$t3,$t4,$out[6]
xxpermdi $t2,$in2[7],$in2[6],0b00
vmsumudm $out[7],$t1,$t2,$vzero
xxpermdi $t4,$in2[5],$in2[4],0b00
vmsumudm $out[7],$t3,$t4,$out[7]
xxpermdi $t2,$in2[8],$in2[7],0b00
vmsumudm $out[8],$t1,$t2,$vzero
xxpermdi $t4,$in2[6],$in2[5],0b00
vmsumudm $out[8],$t3,$t4,$out[8]
xxpermdi $t1,$in1[4],$in1[5],0b00
xxpermdi $t2,$in2[1],$in2[0],0b00
vmsumudm $out[5],$t1,$t2,$out[5]
xxpermdi $t2,$in2[2],$in2[1],0b00
vmsumudm $out[6],$t1,$t2,$out[6]
vmsumudm $out[6],$in1[6],$in2[0],$out[6]
xxpermdi $t2,$in2[3],$in2[2],0b00
vmsumudm $out[7],$t1,$t2,$out[7]
xxpermdi $t3,$in1[6],$in1[7],0b00
xxpermdi $t4,$in2[1],$in2[0],0b00
vmsumudm $out[7],$t3,$t4,$out[7]
xxpermdi $t2,$in2[4],$in2[3],0b00
vmsumudm $out[8],$t1,$t2,$out[8]
xxpermdi $t4,$in2[2],$in2[1],0b00
vmsumudm $out[8],$t3,$t4,$out[8]
vmsumudm $out[8],$in1[8],$in2[0],$out[8]
li $zero,0
li $one,1
mtvsrdd $t1,$one,$zero
___
for (my $i = 0; $i <= 8; $i++) {
$code.=<<___;
vsld $in2[$i],$in2[$i],$t1
___
}
$code.=<<___;
vmsumudm $out[7],$in1[8],$in2[8],$out[7]
xxpermdi $t2,$in2[8],$in2[7],0b00
xxpermdi $t1,$in1[7],$in1[8],0b00
vmsumudm $out[6],$t1,$t2,$out[6]
xxpermdi $t1,$in1[6],$in1[7],0b00
vmsumudm $out[5],$t1,$t2,$out[5]
vmsumudm $out[5],$in1[8],$in2[6],$out[5]
xxpermdi $t1,$in1[5],$in1[6],0b00
vmsumudm $out[4],$t1,$t2,$out[4]
xxpermdi $t4,$in2[6],$in2[5],0b00
xxpermdi $t3,$in1[7],$in1[8],0b00
vmsumudm $out[4],$t3,$t4,$out[4]
xxpermdi $t1,$in1[4],$in1[5],0b00
vmsumudm $out[3],$t1,$t2,$out[3]
xxpermdi $t3,$in1[6],$in1[7],0b00
vmsumudm $out[3],$t3,$t4,$out[3]
vmsumudm $out[3],$in1[8],$in2[4],$out[3]
xxpermdi $t1,$in1[3],$in1[4],0b00
vmsumudm $out[2],$t1,$t2,$out[2]
xxpermdi $t3,$in1[5],$in1[6],0b00
vmsumudm $out[2],$t3,$t4,$out[2]
xxpermdi $t1,$in1[2],$in1[3],0b00
vmsumudm $out[1],$t1,$t2,$out[1]
xxpermdi $t3,$in1[4],$in1[5],0b00
vmsumudm $out[1],$t3,$t4,$out[1]
xxpermdi $t1,$in1[1],$in1[2],0b00
vmsumudm $out[0],$t1,$t2,$out[0]
xxpermdi $t3,$in1[3],$in1[4],0b00
vmsumudm $out[0],$t3,$t4,$out[0]
xxpermdi $t2,$in2[4],$in2[3],0b00
xxpermdi $t1,$in1[7],$in1[8],0b00
vmsumudm $out[2],$t1,$t2,$out[2]
xxpermdi $t1,$in1[6],$in1[7],0b00
vmsumudm $out[1],$t1,$t2,$out[1]
vmsumudm $out[1],$in1[8],$in2[2],$out[1]
xxpermdi $t1,$in1[5],$in1[6],0b00
vmsumudm $out[0],$t1,$t2,$out[0]
xxpermdi $t4,$in2[2],$in2[1],0b00
xxpermdi $t3,$in1[7],$in1[8],0b00
vmsumudm $out[0],$t3,$t4,$out[0]
___
store_vrs($outp, \@out);
pop_vrs(52, 63);
endproc("p521_felem_mul");
}
{
#
# p51_felem_square
#
my ($inp) = ("r4");
my @in = map("v$_",(45..53));
my @inx2 = map("v$_",(35..43));
startproc("p521_felem_square");
push_vrs(52, 63);
$code.=<<___;
vspltisw $vzero,0
___
load_vrs($inp, \@in);
$code.=<<___;
li $zero,0
li $one,1
mtvsrdd $t1,$one,$zero
___
for (my $i = 0; $i <= 8; $i++) {
$code.=<<___;
vsld $inx2[$i],$in[$i],$t1
___
}
$code.=<<___;
vmsumudm $out[0],$in[0],$in[0],$vzero
vmsumudm $out[1],$in[0],$inx2[1],$vzero
xxpermdi $t1,$in[0],$in[1],0b00
xxpermdi $t2,$inx2[2],$in[1],0b00
vmsumudm $out[2],$t1,$t2,$vzero
xxpermdi $t2,$inx2[3],$inx2[2],0b00
vmsumudm $out[3],$t1,$t2,$vzero
xxpermdi $t2,$inx2[4],$inx2[3],0b00
vmsumudm $out[4],$t1,$t2,$vzero
vmsumudm $out[4],$in[2],$in[2],$out[4]
xxpermdi $t2,$inx2[5],$inx2[4],0b00
vmsumudm $out[5],$t1,$t2,$vzero
vmsumudm $out[5],$in[2],$inx2[3],$out[5]
xxpermdi $t2,$inx2[6],$inx2[5],0b00
vmsumudm $out[6],$t1,$t2,$vzero
xxpermdi $t3,$in[2],$in[3],0b00
xxpermdi $t4,$inx2[4],$in[3],0b00
vmsumudm $out[6],$t3,$t4,$out[6]
xxpermdi $t2,$inx2[7],$inx2[6],0b00
vmsumudm $out[7],$t1,$t2,$vzero
xxpermdi $t4,$inx2[5],$inx2[4],0b00
vmsumudm $out[7],$t3,$t4,$out[7]
xxpermdi $t2,$inx2[8],$inx2[7],0b00
vmsumudm $out[8],$t1,$t2,$vzero
xxpermdi $t4,$inx2[6],$inx2[5],0b00
vmsumudm $out[8],$t3,$t4,$out[8]
vmsumudm $out[8],$in[4],$in[4],$out[8]
vmsumudm $out[1],$in[5],$inx2[5],$out[1]
vmsumudm $out[3],$in[6],$inx2[6],$out[3]
vmsumudm $out[5],$in[7],$inx2[7],$out[5]
vmsumudm $out[7],$in[8],$inx2[8],$out[7]
mtvsrdd $t1,$one,$zero
___
for (my $i = 5; $i <= 8; $i++) {
$code.=<<___;
vsld $inx2[$i],$inx2[$i],$t1
___
}
$code.=<<___;
vmsumudm $out[6],$in[7],$inx2[8],$out[6]
vmsumudm $out[5],$in[6],$inx2[8],$out[5]
xxpermdi $t2,$inx2[8],$inx2[7],0b00
xxpermdi $t1,$in[5],$in[6],0b00
vmsumudm $out[4],$t1,$t2,$out[4]
xxpermdi $t1,$in[4],$in[5],0b00
vmsumudm $out[3],$t1,$t2,$out[3]
xxpermdi $t1,$in[3],$in[4],0b00
vmsumudm $out[2],$t1,$t2,$out[2]
vmsumudm $out[2],$in[5],$inx2[6],$out[2]
xxpermdi $t1,$in[2],$in[3],0b00
vmsumudm $out[1],$t1,$t2,$out[1]
vmsumudm $out[1],$in[4],$inx2[6],$out[1]
xxpermdi $t1,$in[1],$in[2],0b00
vmsumudm $out[0],$t1,$t2,$out[0]
xxpermdi $t2,$inx2[6],$inx2[5],0b00
xxpermdi $t1,$in[3],$in[4],0b00
vmsumudm $out[0],$t1,$t2,$out[0]
___
store_vrs($outp, \@out);
pop_vrs(52, 63);
endproc("p521_felem_square");
}
}
$code =~ s/\`([^\`]*)\`/eval $1/gem;
print $code;
close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c
index 4d6f2a76ad20..480376686b9e 100644
--- a/crypto/ec/ec_err.c
+++ b/crypto/ec/ec_err.c
@@ -1,135 +1,136 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <openssl/err.h>
#include <openssl/ecerr.h>
#include "crypto/ecerr.h"
#ifndef OPENSSL_NO_EC
# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA EC_str_reasons[] = {
{ERR_PACK(ERR_LIB_EC, 0, EC_R_ASN1_ERROR), "asn1 error"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_BAD_SIGNATURE), "bad signature"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_BIGNUM_OUT_OF_RANGE), "bignum out of range"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_BUFFER_TOO_SMALL), "buffer too small"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_CANNOT_INVERT), "cannot invert"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_COORDINATES_OUT_OF_RANGE),
"coordinates out of range"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH),
"curve does not support ecdh"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA),
"curve does not support ecdsa"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING),
"curve does not support signing"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_DECODE_ERROR), "decode error"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_DISCRIMINANT_IS_ZERO),
"discriminant is zero"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),
"ec group new by name failure"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED),
"explicit params not supported"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_FAILED_MAKING_PUBLIC_KEY),
"failed making public key"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_FIELD_TOO_LARGE), "field too large"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_GF2M_NOT_SUPPORTED), "gf2m not supported"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_GROUP2PKPARAMETERS_FAILURE),
"group2pkparameters failure"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_I2D_ECPKPARAMETERS_FAILURE),
"i2d ecpkparameters failure"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INCOMPATIBLE_OBJECTS),
"incompatible objects"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_A), "invalid a"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_ARGUMENT), "invalid argument"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_B), "invalid b"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COFACTOR), "invalid cofactor"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COMPRESSED_POINT),
"invalid compressed point"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COMPRESSION_BIT),
"invalid compression bit"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_CURVE), "invalid curve"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_DIGEST), "invalid digest"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_DIGEST_TYPE), "invalid digest type"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_ENCODING), "invalid encoding"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_FIELD), "invalid field"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_FORM), "invalid form"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_GENERATOR), "invalid generator"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_GROUP_ORDER), "invalid group order"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_KEY), "invalid key"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_LENGTH), "invalid length"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_NAMED_GROUP_CONVERSION),
"invalid named group conversion"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_OUTPUT_LENGTH),
"invalid output length"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_P), "invalid p"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PEER_KEY), "invalid peer key"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PENTANOMIAL_BASIS),
"invalid pentanomial basis"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PRIVATE_KEY), "invalid private key"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_SEED), "invalid seed"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_TRINOMIAL_BASIS),
"invalid trinomial basis"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_KDF_PARAMETER_ERROR), "kdf parameter error"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_KEYS_NOT_SET), "keys not set"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_LADDER_POST_FAILURE), "ladder post failure"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_LADDER_PRE_FAILURE), "ladder pre failure"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_LADDER_STEP_FAILURE), "ladder step failure"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_MISSING_OID), "missing OID"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_MISSING_PARAMETERS), "missing parameters"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_MISSING_PRIVATE_KEY), "missing private key"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_NEED_NEW_SETUP_VALUES),
"need new setup values"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_NOT_A_NIST_PRIME), "not a NIST prime"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_NOT_IMPLEMENTED), "not implemented"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_NOT_INITIALIZED), "not initialized"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_NO_PARAMETERS_SET), "no parameters set"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_NO_PRIVATE_VALUE), "no private value"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_OPERATION_NOT_SUPPORTED),
"operation not supported"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_PASSED_NULL_PARAMETER),
"passed null parameter"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_PEER_KEY_ERROR), "peer key error"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_ARITHMETIC_FAILURE),
"point arithmetic failure"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_AT_INFINITY), "point at infinity"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_COORDINATES_BLIND_FAILURE),
"point coordinates blind failure"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_IS_NOT_ON_CURVE),
"point is not on curve"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_RANDOM_NUMBER_GENERATION_FAILED),
"random number generation failed"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_SHARED_INFO_ERROR), "shared info error"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_SLOT_FULL), "slot full"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_TOO_MANY_RETRIES), "too many retries"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_GENERATOR), "undefined generator"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_ORDER), "undefined order"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_COFACTOR), "unknown cofactor"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_GROUP), "unknown group"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_ORDER), "unknown order"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNSUPPORTED_FIELD), "unsupported field"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_WRONG_CURVE_PARAMETERS),
"wrong curve parameters"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_WRONG_ORDER), "wrong order"},
{0, NULL}
};
# endif
int ossl_err_load_EC_strings(void)
{
# ifndef OPENSSL_NO_ERR
if (ERR_reason_error_string(EC_str_reasons[0].error) == NULL)
ERR_load_strings_const(EC_str_reasons);
# endif
return 1;
}
#else
NON_EMPTY_TRANSLATION_UNIT
#endif
diff --git a/crypto/ec/ecdsa_ossl.c b/crypto/ec/ecdsa_ossl.c
index fe9b3cf59363..0bf4635e2f97 100644
--- a/crypto/ec/ecdsa_ossl.c
+++ b/crypto/ec/ecdsa_ossl.c
@@ -1,464 +1,481 @@
/*
- * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/*
* 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/obj_mac.h>
#include <openssl/rand.h>
#include "crypto/bn.h"
#include "ec_local.h"
+#define MIN_ECDSA_SIGN_ORDERBITS 64
+/*
+ * It is highly unlikely that a retry will happen,
+ * Multiple retries would indicate that something is wrong
+ * with the group parameters (which would normally only happen
+ * with a bad custom group).
+ */
+#define MAX_ECDSA_SIGN_RETRIES 8
+
int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp)
{
if (eckey->group->meth->ecdsa_sign_setup == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA);
return 0;
}
return eckey->group->meth->ecdsa_sign_setup(eckey, ctx_in, kinvp, rp);
}
ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
const BIGNUM *in_kinv, const BIGNUM *in_r,
EC_KEY *eckey)
{
if (eckey->group->meth->ecdsa_sign_sig == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA);
return NULL;
}
return eckey->group->meth->ecdsa_sign_sig(dgst, dgst_len,
in_kinv, in_r, eckey);
}
int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey)
{
if (eckey->group->meth->ecdsa_verify_sig == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA);
return 0;
}
return eckey->group->meth->ecdsa_verify_sig(dgst, dgst_len, sig, eckey);
}
int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen,
const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey)
{
ECDSA_SIG *s;
s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey);
if (s == NULL) {
*siglen = 0;
return 0;
}
- *siglen = i2d_ECDSA_SIG(s, &sig);
+ *siglen = i2d_ECDSA_SIG(s, sig != NULL ? &sig : NULL);
ECDSA_SIG_free(s);
return 1;
}
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
BIGNUM **kinvp, BIGNUM **rp,
const unsigned char *dgst, int dlen)
{
BN_CTX *ctx = NULL;
BIGNUM *k = NULL, *r = NULL, *X = NULL;
const BIGNUM *order;
EC_POINT *tmp_point = NULL;
const EC_GROUP *group;
int ret = 0;
int order_bits;
const BIGNUM *priv_key;
if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((priv_key = EC_KEY_get0_private_key(eckey)) == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY);
return 0;
}
if (!EC_KEY_can_sign(eckey)) {
ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
return 0;
}
if ((ctx = ctx_in) == NULL) {
if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
}
k = BN_secure_new(); /* this value is later returned in *kinvp */
r = BN_new(); /* this value is later returned in *rp */
X = BN_new();
if (k == NULL || r == NULL || X == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if ((tmp_point = EC_POINT_new(group)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
order = EC_GROUP_get0_order(group);
/* Preallocate space */
order_bits = BN_num_bits(order);
- if (!BN_set_bit(k, order_bits)
+ /* Check the number of bits here so that an infinite loop is not possible */
+ if (order_bits < MIN_ECDSA_SIGN_ORDERBITS
+ || !BN_set_bit(k, order_bits)
|| !BN_set_bit(r, order_bits)
|| !BN_set_bit(X, order_bits))
goto err;
do {
/* get random k */
do {
if (dgst != NULL) {
if (!BN_generate_dsa_nonce(k, order, priv_key,
dgst, dlen, ctx)) {
ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
goto err;
}
} else {
if (!BN_priv_rand_range_ex(k, order, 0, ctx)) {
ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
goto err;
}
}
} while (BN_is_zero(k));
/* compute r the x-coordinate of generator * k */
if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (!EC_POINT_get_affine_coordinates(group, tmp_point, X, NULL, ctx)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (!BN_nnmod(r, X, order, ctx)) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
} while (BN_is_zero(r));
/* compute the inverse of k */
if (!ossl_ec_group_do_inverse_ord(group, k, k, ctx)) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* clear old values if necessary */
BN_clear_free(*rp);
BN_clear_free(*kinvp);
/* save the pre-computed values */
*rp = r;
*kinvp = k;
ret = 1;
err:
if (!ret) {
BN_clear_free(k);
BN_clear_free(r);
}
if (ctx != ctx_in)
BN_CTX_free(ctx);
EC_POINT_free(tmp_point);
BN_clear_free(X);
return ret;
}
int ossl_ecdsa_simple_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp)
{
return ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0);
}
ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len,
const BIGNUM *in_kinv, const BIGNUM *in_r,
EC_KEY *eckey)
{
int ok = 0, i;
+ int retries = 0;
BIGNUM *kinv = NULL, *s, *m = NULL;
const BIGNUM *order, *ckinv;
BN_CTX *ctx = NULL;
const EC_GROUP *group;
ECDSA_SIG *ret;
const BIGNUM *priv_key;
group = EC_KEY_get0_group(eckey);
priv_key = EC_KEY_get0_private_key(eckey);
if (group == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (priv_key == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY);
return NULL;
}
if (!EC_KEY_can_sign(eckey)) {
ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
return NULL;
}
ret = ECDSA_SIG_new();
if (ret == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->r = BN_new();
ret->s = BN_new();
if (ret->r == NULL || ret->s == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
s = ret->s;
if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL
|| (m = BN_new()) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
order = EC_GROUP_get0_order(group);
i = BN_num_bits(order);
/*
* Need to truncate digest if it is too long: first truncate whole bytes.
*/
if (8 * dgst_len > i)
dgst_len = (i + 7) / 8;
if (!BN_bin2bn(dgst, dgst_len, m)) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* If still too long, truncate remaining bits with a shift */
if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
do {
if (in_kinv == NULL || in_r == NULL) {
if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len)) {
ERR_raise(ERR_LIB_EC, ERR_R_ECDSA_LIB);
goto err;
}
ckinv = kinv;
} else {
ckinv = in_kinv;
if (BN_copy(ret->r, in_r) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
}
/*
* With only one multiplicant being in Montgomery domain
* multiplication yields real result without post-conversion.
* Also note that all operations but last are performed with
* zero-padded vectors. Last operation, BN_mod_mul_montgomery
* below, returns user-visible value with removed zero padding.
*/
if (!bn_to_mont_fixed_top(s, ret->r, group->mont_data, ctx)
|| !bn_mul_mont_fixed_top(s, s, priv_key, group->mont_data, ctx)) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
if (!bn_mod_add_fixed_top(s, s, m, order)) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/*
* |s| can still be larger than modulus, because |m| can be. In
* such case we count on Montgomery reduction to tie it up.
*/
if (!bn_to_mont_fixed_top(s, s, group->mont_data, ctx)
|| !BN_mod_mul_montgomery(s, s, ckinv, group->mont_data, ctx)) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
if (BN_is_zero(s)) {
/*
* if kinv and r have been supplied by the caller, don't
* generate new kinv and r values
*/
if (in_kinv != NULL && in_r != NULL) {
ERR_raise(ERR_LIB_EC, EC_R_NEED_NEW_SETUP_VALUES);
goto err;
}
+ /* Avoid infinite loops cause by invalid group parameters */
+ if (retries++ > MAX_ECDSA_SIGN_RETRIES) {
+ ERR_raise(ERR_LIB_EC, EC_R_TOO_MANY_RETRIES);
+ goto err;
+ }
} else {
/* s != 0 => we have a valid signature */
break;
}
} while (1);
ok = 1;
err:
if (!ok) {
ECDSA_SIG_free(ret);
ret = NULL;
}
BN_CTX_free(ctx);
BN_clear_free(m);
BN_clear_free(kinv);
return ret;
}
/*-
* returns
* 1: correct signature
* 0: incorrect signature
* -1: error
*/
int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len,
const unsigned char *sigbuf, int sig_len, EC_KEY *eckey)
{
ECDSA_SIG *s;
const unsigned char *p = sigbuf;
unsigned char *der = NULL;
int derlen = -1;
int ret = -1;
s = ECDSA_SIG_new();
if (s == NULL)
return ret;
if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL)
goto err;
/* Ensure signature uses DER and doesn't have trailing garbage */
derlen = i2d_ECDSA_SIG(s, &der);
if (derlen != sig_len || memcmp(sigbuf, der, derlen) != 0)
goto err;
ret = ECDSA_do_verify(dgst, dgst_len, s, eckey);
err:
OPENSSL_free(der);
ECDSA_SIG_free(s);
return ret;
}
int ossl_ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey)
{
int ret = -1, i;
BN_CTX *ctx;
const BIGNUM *order;
BIGNUM *u1, *u2, *m, *X;
EC_POINT *point = NULL;
const EC_GROUP *group;
const EC_POINT *pub_key;
/* check input values */
if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL ||
(pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
return -1;
}
if (!EC_KEY_can_sign(eckey)) {
ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
return -1;
}
ctx = BN_CTX_new_ex(eckey->libctx);
if (ctx == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return -1;
}
BN_CTX_start(ctx);
u1 = BN_CTX_get(ctx);
u2 = BN_CTX_get(ctx);
m = BN_CTX_get(ctx);
X = BN_CTX_get(ctx);
if (X == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
order = EC_GROUP_get0_order(group);
if (order == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) ||
BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) {
ERR_raise(ERR_LIB_EC, EC_R_BAD_SIGNATURE);
ret = 0; /* signature is invalid */
goto err;
}
/* calculate tmp1 = inv(S) mod order */
if (!ossl_ec_group_do_inverse_ord(group, u2, sig->s, ctx)) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* digest -> m */
i = BN_num_bits(order);
/*
* Need to truncate digest if it is too long: first truncate whole bytes.
*/
if (8 * dgst_len > i)
dgst_len = (i + 7) / 8;
if (!BN_bin2bn(dgst, dgst_len, m)) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* If still too long truncate remaining bits with a shift */
if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* u1 = m * tmp mod order */
if (!BN_mod_mul(u1, m, u2, order, ctx)) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* u2 = r * w mod q */
if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
if ((point = EC_POINT_new(group)) == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (!EC_POINT_get_affine_coordinates(group, point, X, NULL, ctx)) {
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
goto err;
}
if (!BN_nnmod(u1, X, order, ctx)) {
ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
goto err;
}
/* if the signature is correct u1 is equal to sig->r */
ret = (BN_ucmp(u1, sig->r) == 0);
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
EC_POINT_free(point);
return ret;
}
diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c
index 4e32210bf436..c97dc472ac57 100644
--- a/crypto/ec/ecx_meth.c
+++ b/crypto/ec/ecx_meth.c
@@ -1,1424 +1,1424 @@
/*
- * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/*
* ECDSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <stdio.h>
#include <openssl/x509.h>
#include <openssl/ec.h>
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#include <openssl/rand.h>
#include "internal/cryptlib.h"
#include "internal/provider.h"
#include "crypto/asn1.h"
#include "crypto/evp.h"
#include "crypto/ecx.h"
#include "ec_local.h"
#include "curve448/curve448_local.h"
#include "ecx_backend.h"
static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
{
const ECX_KEY *ecxkey = pkey->pkey.ecx;
unsigned char *penc;
if (ecxkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
return 0;
}
penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey));
if (penc == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
V_ASN1_UNDEF, NULL, penc, KEYLEN(pkey))) {
OPENSSL_free(penc);
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
static int ecx_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
{
const unsigned char *p;
int pklen;
X509_ALGOR *palg;
ECX_KEY *ecx;
int ret = 0;
if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
return 0;
ecx = ossl_ecx_key_op(palg, p, pklen, pkey->ameth->pkey_id,
KEY_OP_PUBLIC, NULL, NULL);
if (ecx != NULL) {
ret = 1;
EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
}
return ret;
}
static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
{
const ECX_KEY *akey = a->pkey.ecx;
const ECX_KEY *bkey = b->pkey.ecx;
if (akey == NULL || bkey == NULL)
return -2;
return CRYPTO_memcmp(akey->pubkey, bkey->pubkey, KEYLEN(a)) == 0;
}
static int ecx_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8,
OSSL_LIB_CTX *libctx, const char *propq)
{
int ret = 0;
ECX_KEY *ecx = ossl_ecx_key_from_pkcs8(p8, libctx, propq);
if (ecx != NULL) {
ret = 1;
EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
}
return ret;
}
static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
{
const ECX_KEY *ecxkey = pkey->pkey.ecx;
ASN1_OCTET_STRING oct;
unsigned char *penc = NULL;
int penclen;
if (ecxkey == NULL || ecxkey->privkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
return 0;
}
oct.data = ecxkey->privkey;
oct.length = KEYLEN(pkey);
oct.flags = 0;
penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
if (penclen < 0) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
V_ASN1_UNDEF, NULL, penc, penclen)) {
OPENSSL_clear_free(penc, penclen);
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
static int ecx_size(const EVP_PKEY *pkey)
{
return KEYLEN(pkey);
}
static int ecx_bits(const EVP_PKEY *pkey)
{
if (IS25519(pkey->ameth->pkey_id)) {
return X25519_BITS;
} else if(ISX448(pkey->ameth->pkey_id)) {
return X448_BITS;
} else {
return ED448_BITS;
}
}
static int ecx_security_bits(const EVP_PKEY *pkey)
{
if (IS25519(pkey->ameth->pkey_id)) {
return X25519_SECURITY_BITS;
} else {
return X448_SECURITY_BITS;
}
}
static void ecx_free(EVP_PKEY *pkey)
{
ossl_ecx_key_free(pkey->pkey.ecx);
}
/* "parameters" are always equal */
static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
{
return 1;
}
static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *ctx, ecx_key_op_t op)
{
const ECX_KEY *ecxkey = pkey->pkey.ecx;
const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id);
if (op == KEY_OP_PRIVATE) {
if (ecxkey == NULL || ecxkey->privkey == NULL) {
if (BIO_printf(bp, "%*s<INVALID PRIVATE KEY>\n", indent, "") <= 0)
return 0;
return 1;
}
if (BIO_printf(bp, "%*s%s Private-Key:\n", indent, "", nm) <= 0)
return 0;
if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
return 0;
if (ASN1_buf_print(bp, ecxkey->privkey, KEYLEN(pkey),
indent + 4) == 0)
return 0;
} else {
if (ecxkey == NULL) {
if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
return 0;
return 1;
}
if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
return 0;
}
if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
return 0;
if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
indent + 4) == 0)
return 0;
return 1;
}
static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *ctx)
{
return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
}
static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *ctx)
{
return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PUBLIC);
}
static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
switch (op) {
case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: {
ECX_KEY *ecx = ossl_ecx_key_op(NULL, arg2, arg1, pkey->ameth->pkey_id,
KEY_OP_PUBLIC, NULL, NULL);
if (ecx != NULL) {
EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
return 1;
}
return 0;
}
case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
if (pkey->pkey.ecx != NULL) {
unsigned char **ppt = arg2;
*ppt = OPENSSL_memdup(pkey->pkey.ecx->pubkey, KEYLEN(pkey));
if (*ppt != NULL)
return KEYLEN(pkey);
}
return 0;
default:
return -2;
}
}
static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
switch (op) {
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
/* We currently only support Pure EdDSA which takes no digest */
*(int *)arg2 = NID_undef;
return 2;
default:
return -2;
}
}
static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
size_t len)
{
OSSL_LIB_CTX *libctx = NULL;
ECX_KEY *ecx = NULL;
if (pkey->keymgmt != NULL)
libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt));
ecx = ossl_ecx_key_op(NULL, priv, len, pkey->ameth->pkey_id,
KEY_OP_PRIVATE, libctx, NULL);
if (ecx != NULL) {
EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
return 1;
}
return 0;
}
static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len)
{
OSSL_LIB_CTX *libctx = NULL;
ECX_KEY *ecx = NULL;
if (pkey->keymgmt != NULL)
libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt));
ecx = ossl_ecx_key_op(NULL, pub, len, pkey->ameth->pkey_id,
KEY_OP_PUBLIC, libctx, NULL);
if (ecx != NULL) {
EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
return 1;
}
return 0;
}
static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
size_t *len)
{
const ECX_KEY *key = pkey->pkey.ecx;
if (priv == NULL) {
*len = KEYLENID(pkey->ameth->pkey_id);
return 1;
}
if (key == NULL
|| key->privkey == NULL
|| *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
return 0;
*len = KEYLENID(pkey->ameth->pkey_id);
memcpy(priv, key->privkey, *len);
return 1;
}
static int ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *pub,
size_t *len)
{
const ECX_KEY *key = pkey->pkey.ecx;
if (pub == NULL) {
*len = KEYLENID(pkey->ameth->pkey_id);
return 1;
}
if (key == NULL
|| *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
return 0;
*len = KEYLENID(pkey->ameth->pkey_id);
memcpy(pub, key->pubkey, *len);
return 1;
}
static size_t ecx_pkey_dirty_cnt(const EVP_PKEY *pkey)
{
/*
* We provide no mechanism to "update" an ECX key once it has been set,
* therefore we do not have to maintain a dirty count.
*/
return 1;
}
static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
OSSL_FUNC_keymgmt_import_fn *importer,
OSSL_LIB_CTX *libctx, const char *propq)
{
const ECX_KEY *key = from->pkey.ecx;
OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
OSSL_PARAM *params = NULL;
int selection = 0;
int rv = 0;
if (tmpl == NULL)
return 0;
/* A key must at least have a public part */
if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
key->pubkey, key->keylen))
goto err;
selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
if (key->privkey != NULL) {
if (!OSSL_PARAM_BLD_push_octet_string(tmpl,
OSSL_PKEY_PARAM_PRIV_KEY,
key->privkey, key->keylen))
goto err;
selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
}
params = OSSL_PARAM_BLD_to_param(tmpl);
/* We export, the provider imports */
rv = importer(to_keydata, selection, params);
err:
OSSL_PARAM_BLD_free(tmpl);
OSSL_PARAM_free(params);
return rv;
}
static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx,
int keytype)
{
EVP_PKEY_CTX *pctx = vpctx;
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
ECX_KEY *ecx = ossl_ecx_key_new(pctx->libctx, KEYNID2TYPE(keytype), 0,
pctx->propquery);
if (ecx == NULL) {
ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!ossl_ecx_key_fromdata(ecx, params, 1)
|| !EVP_PKEY_assign(pkey, keytype, ecx)) {
ossl_ecx_key_free(ecx);
return 0;
}
return 1;
}
static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
{
ECX_KEY *ecx = from->pkey.ecx, *dupkey = NULL;
int ret;
if (ecx != NULL) {
dupkey = ossl_ecx_key_dup(ecx, OSSL_KEYMGMT_SELECT_ALL);
if (dupkey == NULL)
return 0;
}
ret = EVP_PKEY_assign(to, from->type, dupkey);
if (!ret)
ossl_ecx_key_free(dupkey);
return ret;
}
static int x25519_import_from(const OSSL_PARAM params[], void *vpctx)
{
return ecx_generic_import_from(params, vpctx, EVP_PKEY_X25519);
}
const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth = {
EVP_PKEY_X25519,
EVP_PKEY_X25519,
0,
"X25519",
"OpenSSL X25519 algorithm",
ecx_pub_decode,
ecx_pub_encode,
ecx_pub_cmp,
ecx_pub_print,
NULL,
ecx_priv_encode,
ecx_priv_print,
ecx_size,
ecx_bits,
ecx_security_bits,
0, 0, 0, 0,
ecx_cmp_parameters,
0, 0,
ecx_free,
ecx_ctrl,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
ecx_set_priv_key,
ecx_set_pub_key,
ecx_get_priv_key,
ecx_get_pub_key,
ecx_pkey_dirty_cnt,
ecx_pkey_export_to,
x25519_import_from,
ecx_pkey_copy,
ecx_priv_decode_ex
};
static int x448_import_from(const OSSL_PARAM params[], void *vpctx)
{
return ecx_generic_import_from(params, vpctx, EVP_PKEY_X448);
}
const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth = {
EVP_PKEY_X448,
EVP_PKEY_X448,
0,
"X448",
"OpenSSL X448 algorithm",
ecx_pub_decode,
ecx_pub_encode,
ecx_pub_cmp,
ecx_pub_print,
NULL,
ecx_priv_encode,
ecx_priv_print,
ecx_size,
ecx_bits,
ecx_security_bits,
0, 0, 0, 0,
ecx_cmp_parameters,
0, 0,
ecx_free,
ecx_ctrl,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
ecx_set_priv_key,
ecx_set_pub_key,
ecx_get_priv_key,
ecx_get_pub_key,
ecx_pkey_dirty_cnt,
ecx_pkey_export_to,
x448_import_from,
ecx_pkey_copy,
ecx_priv_decode_ex
};
static int ecd_size25519(const EVP_PKEY *pkey)
{
return ED25519_SIGSIZE;
}
static int ecd_size448(const EVP_PKEY *pkey)
{
return ED448_SIGSIZE;
}
static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
const void *asn, const X509_ALGOR *sigalg,
const ASN1_BIT_STRING *str, EVP_PKEY *pkey)
{
const ASN1_OBJECT *obj;
int ptype;
int nid;
/* Sanity check: make sure it is ED25519/ED448 with absent parameters */
X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
nid = OBJ_obj2nid(obj);
if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
return 0;
}
if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
return 0;
return 2;
}
static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
const void *asn,
X509_ALGOR *alg1, X509_ALGOR *alg2,
ASN1_BIT_STRING *str)
{
/* Set algorithms identifiers */
X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
if (alg2)
X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
/* Algorithm identifiers set: carry on as normal */
return 3;
}
static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
const ASN1_STRING *sig)
{
X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
X509_SIG_INFO_TLS);
return 1;
}
static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
const void *asn,
X509_ALGOR *alg1, X509_ALGOR *alg2,
ASN1_BIT_STRING *str)
{
/* Set algorithm identifier */
X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
if (alg2 != NULL)
X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
/* Algorithm identifier set: carry on as normal */
return 3;
}
static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
const ASN1_STRING *sig)
{
X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
X509_SIG_INFO_TLS);
return 1;
}
static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx)
{
return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519);
}
const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = {
EVP_PKEY_ED25519,
EVP_PKEY_ED25519,
0,
"ED25519",
"OpenSSL ED25519 algorithm",
ecx_pub_decode,
ecx_pub_encode,
ecx_pub_cmp,
ecx_pub_print,
NULL,
ecx_priv_encode,
ecx_priv_print,
ecd_size25519,
ecx_bits,
ecx_security_bits,
0, 0, 0, 0,
ecx_cmp_parameters,
0, 0,
ecx_free,
ecd_ctrl,
NULL,
NULL,
ecd_item_verify,
ecd_item_sign25519,
ecd_sig_info_set25519,
NULL,
NULL,
NULL,
ecx_set_priv_key,
ecx_set_pub_key,
ecx_get_priv_key,
ecx_get_pub_key,
ecx_pkey_dirty_cnt,
ecx_pkey_export_to,
ed25519_import_from,
ecx_pkey_copy,
ecx_priv_decode_ex
};
static int ed448_import_from(const OSSL_PARAM params[], void *vpctx)
{
return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448);
}
const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = {
EVP_PKEY_ED448,
EVP_PKEY_ED448,
0,
"ED448",
"OpenSSL ED448 algorithm",
ecx_pub_decode,
ecx_pub_encode,
ecx_pub_cmp,
ecx_pub_print,
NULL,
ecx_priv_encode,
ecx_priv_print,
ecd_size448,
ecx_bits,
ecx_security_bits,
0, 0, 0, 0,
ecx_cmp_parameters,
0, 0,
ecx_free,
ecd_ctrl,
NULL,
NULL,
ecd_item_verify,
ecd_item_sign448,
ecd_sig_info_set448,
NULL,
NULL,
NULL,
ecx_set_priv_key,
ecx_set_pub_key,
ecx_get_priv_key,
ecx_get_pub_key,
ecx_pkey_dirty_cnt,
ecx_pkey_export_to,
ed448_import_from,
ecx_pkey_copy,
ecx_priv_decode_ex
};
static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
ECX_KEY *ecx = ossl_ecx_key_op(NULL, NULL, 0, ctx->pmeth->pkey_id,
- KEY_OP_PUBLIC, NULL, NULL);
+ KEY_OP_KEYGEN, NULL, NULL);
if (ecx != NULL) {
EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, ecx);
return 1;
}
return 0;
}
static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen,
const unsigned char **privkey,
const unsigned char **pubkey)
{
const ECX_KEY *ecxkey, *peerkey;
if (ctx->pkey == NULL || ctx->peerkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
return 0;
}
ecxkey = evp_pkey_get_legacy(ctx->pkey);
peerkey = evp_pkey_get_legacy(ctx->peerkey);
if (ecxkey == NULL || ecxkey->privkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
return 0;
}
if (peerkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_PEER_KEY);
return 0;
}
*privkey = ecxkey->privkey;
*pubkey = peerkey->pubkey;
return 1;
}
static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
{
const unsigned char *privkey, *pubkey;
if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
|| (key != NULL
&& ossl_x25519(key, privkey, pubkey) == 0))
return 0;
*keylen = X25519_KEYLEN;
return 1;
}
static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
{
const unsigned char *privkey, *pubkey;
if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
|| (key != NULL
&& ossl_x448(key, privkey, pubkey) == 0))
return 0;
*keylen = X448_KEYLEN;
return 1;
}
static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
/* Only need to handle peer key for derivation */
if (type == EVP_PKEY_CTRL_PEER_KEY)
return 1;
return -2;
}
static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
EVP_PKEY_X25519,
0, 0, 0, 0, 0, 0, 0,
pkey_ecx_keygen,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pkey_ecx_derive25519,
pkey_ecx_ctrl,
0
};
static const EVP_PKEY_METHOD ecx448_pkey_meth = {
EVP_PKEY_X448,
0, 0, 0, 0, 0, 0, 0,
pkey_ecx_keygen,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pkey_ecx_derive448,
pkey_ecx_ctrl,
0
};
static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
size_t *siglen, const unsigned char *tbs,
size_t tbslen)
{
const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
if (edkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
return 0;
}
if (sig == NULL) {
*siglen = ED25519_SIGSIZE;
return 1;
}
if (*siglen < ED25519_SIGSIZE) {
ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
return 0;
}
if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
NULL) == 0)
return 0;
*siglen = ED25519_SIGSIZE;
return 1;
}
static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
size_t *siglen, const unsigned char *tbs,
size_t tbslen)
{
const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
if (edkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
return 0;
}
if (sig == NULL) {
*siglen = ED448_SIGSIZE;
return 1;
}
if (*siglen < ED448_SIGSIZE) {
ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
return 0;
}
if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
edkey->privkey, NULL, 0, edkey->propq) == 0)
return 0;
*siglen = ED448_SIGSIZE;
return 1;
}
static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs,
size_t tbslen)
{
const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
if (edkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
return 0;
}
if (siglen != ED25519_SIGSIZE)
return 0;
return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
edkey->libctx, edkey->propq);
}
static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs,
size_t tbslen)
{
const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
if (edkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
return 0;
}
if (siglen != ED448_SIGSIZE)
return 0;
return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
NULL, 0, edkey->propq);
}
static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
switch (type) {
case EVP_PKEY_CTRL_MD:
/* Only NULL allowed as digest */
if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
return 1;
ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
return 0;
case EVP_PKEY_CTRL_DIGESTINIT:
return 1;
}
return -2;
}
static const EVP_PKEY_METHOD ed25519_pkey_meth = {
EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
0, 0, 0, 0, 0, 0,
pkey_ecx_keygen,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pkey_ecd_ctrl,
0,
pkey_ecd_digestsign25519,
pkey_ecd_digestverify25519
};
static const EVP_PKEY_METHOD ed448_pkey_meth = {
EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
0, 0, 0, 0, 0, 0,
pkey_ecx_keygen,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pkey_ecd_ctrl,
0,
pkey_ecd_digestsign448,
pkey_ecd_digestverify448
};
#ifdef S390X_EC_ASM
# include "s390x_arch.h"
static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
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(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
ctx->propquery);
unsigned char *privkey = NULL, *pubkey;
if (key == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
pubkey = key->pubkey;
privkey = ossl_ecx_key_allocate_privkey(key);
if (privkey == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (RAND_priv_bytes_ex(ctx->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;
EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
return 1;
err:
ossl_ecx_key_free(key);
return 0;
}
static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
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(ctx->libctx, ECX_KEY_TYPE_X448, 1,
ctx->propquery);
unsigned char *privkey = NULL, *pubkey;
if (key == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
pubkey = key->pubkey;
privkey = ossl_ecx_key_allocate_privkey(key);
if (privkey == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
goto err;
privkey[0] &= 252;
privkey[55] |= 128;
if (s390x_x448_mul(pubkey, generator, privkey) != 1)
goto err;
EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
return 1;
err:
ossl_ecx_key_free(key);
return 0;
}
static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
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(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
ctx->propquery);
unsigned char *privkey = NULL, *pubkey;
unsigned int sz;
EVP_MD *md = NULL;
int rv;
if (key == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
pubkey = key->pubkey;
privkey = ossl_ecx_key_allocate_privkey(key);
if (privkey == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
goto err;
md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
if (md == NULL)
goto err;
rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
EVP_MD_free(md);
if (!rv)
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);
EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
return 1;
err:
ossl_ecx_key_free(key);
return 0;
}
static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
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(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
ctx->propquery);
unsigned char *privkey = NULL, *pubkey;
EVP_MD_CTX *hashctx = NULL;
EVP_MD *md = NULL;
int rv;
if (key == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
pubkey = key->pubkey;
privkey = ossl_ecx_key_allocate_privkey(key);
if (privkey == NULL) {
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
goto err;
}
if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
goto err;
hashctx = EVP_MD_CTX_new();
if (hashctx == NULL)
goto err;
md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
if (md == NULL)
goto err;
rv = EVP_DigestInit_ex(hashctx, md, NULL);
EVP_MD_free(md);
if (rv != 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_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
EVP_MD_CTX_free(hashctx);
return 1;
err:
ossl_ecx_key_free(key);
EVP_MD_CTX_free(hashctx);
return 0;
}
static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
{
const unsigned char *privkey, *pubkey;
if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
|| (key != NULL
&& s390x_x25519_mul(key, privkey, pubkey) == 0))
return 0;
*keylen = X25519_KEYLEN;
return 1;
}
static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
{
const unsigned char *privkey, *pubkey;
if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
|| (key != NULL
&& s390x_x448_mul(key, pubkey, privkey) == 0))
return 0;
*keylen = X448_KEYLEN;
return 1;
}
static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs,
size_t tbslen)
{
union {
struct {
unsigned char sig[64];
unsigned char priv[32];
} ed25519;
unsigned long long buff[512];
} param;
const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
int rc;
if (edkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
return 0;
}
if (sig == NULL) {
*siglen = ED25519_SIGSIZE;
return 1;
}
if (*siglen < ED25519_SIGSIZE) {
ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
return 0;
}
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);
*siglen = ED25519_SIGSIZE;
return 1;
}
static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs,
size_t tbslen)
{
union {
struct {
unsigned char sig[128];
unsigned char priv[64];
} ed448;
unsigned long long buff[512];
} param;
const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
int rc;
if (edkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
return 0;
}
if (sig == NULL) {
*siglen = ED448_SIGSIZE;
return 1;
}
if (*siglen < ED448_SIGSIZE) {
ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
return 0;
}
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);
*siglen = ED448_SIGSIZE;
return 1;
}
static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
const unsigned char *sig,
size_t siglen,
const unsigned char *tbs,
size_t tbslen)
{
union {
struct {
unsigned char sig[64];
unsigned char pub[32];
} ed25519;
unsigned long long buff[512];
} param;
const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
if (edkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
return 0;
}
if (siglen != ED25519_SIGSIZE)
return 0;
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_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
const unsigned char *sig,
size_t siglen,
const unsigned char *tbs,
size_t tbslen)
{
union {
struct {
unsigned char sig[128];
unsigned char pub[64];
} ed448;
unsigned long long buff[512];
} param;
const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
if (edkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
return 0;
}
if (siglen != ED448_SIGSIZE)
return 0;
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;
}
static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
EVP_PKEY_X25519,
0, 0, 0, 0, 0, 0, 0,
s390x_pkey_ecx_keygen25519,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
s390x_pkey_ecx_derive25519,
pkey_ecx_ctrl,
0
};
static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
EVP_PKEY_X448,
0, 0, 0, 0, 0, 0, 0,
s390x_pkey_ecx_keygen448,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
s390x_pkey_ecx_derive448,
pkey_ecx_ctrl,
0
};
static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
0, 0, 0, 0, 0, 0,
s390x_pkey_ecd_keygen25519,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pkey_ecd_ctrl,
0,
s390x_pkey_ecd_digestsign25519,
s390x_pkey_ecd_digestverify25519
};
static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
0, 0, 0, 0, 0, 0,
s390x_pkey_ecd_keygen448,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pkey_ecd_ctrl,
0,
s390x_pkey_ecd_digestsign448,
s390x_pkey_ecd_digestverify448
};
#endif
const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
{
#ifdef S390X_EC_ASM
if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
return &ecx25519_s390x_pkey_meth;
#endif
return &ecx25519_pkey_meth;
}
const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
{
#ifdef S390X_EC_ASM
if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
return &ecx448_s390x_pkey_meth;
#endif
return &ecx448_pkey_meth;
}
const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
{
#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 &ed25519_s390x_pkey_meth;
#endif
return &ed25519_pkey_meth;
}
const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
{
#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 &ed448_s390x_pkey_meth;
#endif
return &ed448_pkey_meth;
}
diff --git a/crypto/engine/eng_lib.c b/crypto/engine/eng_lib.c
index 05c6a67c1e1b..dfd53a433195 100644
--- a/crypto/engine/eng_lib.c
+++ b/crypto/engine/eng_lib.c
@@ -1,300 +1,301 @@
/*
- * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-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 "e_os.h"
#include "eng_local.h"
#include <openssl/rand.h>
#include "internal/refcount.h"
CRYPTO_RWLOCK *global_engine_lock;
CRYPTO_ONCE engine_lock_init = CRYPTO_ONCE_STATIC_INIT;
/* The "new"/"free" stuff first */
DEFINE_RUN_ONCE(do_engine_lock_init)
{
global_engine_lock = CRYPTO_THREAD_lock_new();
return global_engine_lock != NULL;
}
ENGINE *ENGINE_new(void)
{
ENGINE *ret;
if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)
|| (ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->struct_ref = 1;
ENGINE_REF_PRINT(ret, 0, 1);
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ENGINE, ret, &ret->ex_data)) {
OPENSSL_free(ret);
return NULL;
}
return ret;
}
/*
* Placed here (close proximity to ENGINE_new) so that modifications to the
* elements of the ENGINE structure are more likely to be caught and changed
* here.
*/
void engine_set_all_null(ENGINE *e)
{
e->id = NULL;
e->name = NULL;
e->rsa_meth = NULL;
e->dsa_meth = NULL;
e->dh_meth = NULL;
e->rand_meth = NULL;
e->ciphers = NULL;
e->digests = NULL;
e->destroy = NULL;
e->init = NULL;
e->finish = NULL;
e->ctrl = NULL;
e->load_privkey = NULL;
e->load_pubkey = NULL;
e->cmd_defns = NULL;
e->flags = 0;
e->dynamic_id = NULL;
}
int engine_free_util(ENGINE *e, int not_locked)
{
int i;
if (e == NULL)
return 1;
if (not_locked)
CRYPTO_DOWN_REF(&e->struct_ref, &i, global_engine_lock);
else
i = --e->struct_ref;
ENGINE_REF_PRINT(e, 0, -1);
if (i > 0)
return 1;
REF_ASSERT_ISNT(i < 0);
/* Free up any dynamically allocated public key methods */
engine_pkey_meths_free(e);
engine_pkey_asn1_meths_free(e);
/*
* Give the ENGINE a chance to do any structural cleanup corresponding to
* allocation it did in its constructor (eg. unload error strings)
*/
if (e->destroy)
e->destroy(e);
engine_remove_dynamic_id(e, not_locked);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ENGINE, e, &e->ex_data);
OPENSSL_free(e);
return 1;
}
int ENGINE_free(ENGINE *e)
{
return engine_free_util(e, 1);
}
/* Cleanup stuff */
/*
* engine_cleanup_int() is coded such that anything that does work that will
* need cleanup can register a "cleanup" callback here. That way we don't get
* linker bloat by referring to all *possible* cleanups, but any linker bloat
* into code "X" will cause X's cleanup function to end up here.
*/
static STACK_OF(ENGINE_CLEANUP_ITEM) *cleanup_stack = NULL;
static int int_cleanup_check(int create)
{
if (cleanup_stack)
return 1;
if (!create)
return 0;
cleanup_stack = sk_ENGINE_CLEANUP_ITEM_new_null();
return (cleanup_stack ? 1 : 0);
}
static ENGINE_CLEANUP_ITEM *int_cleanup_item(ENGINE_CLEANUP_CB *cb)
{
ENGINE_CLEANUP_ITEM *item;
if ((item = OPENSSL_malloc(sizeof(*item))) == NULL) {
ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
return NULL;
}
item->cb = cb;
return item;
}
void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb)
{
ENGINE_CLEANUP_ITEM *item;
if (!int_cleanup_check(1))
return;
item = int_cleanup_item(cb);
- if (item)
- sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0);
+ if (item != NULL)
+ if (sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0) <= 0)
+ OPENSSL_free(item);
}
void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb)
{
ENGINE_CLEANUP_ITEM *item;
if (!int_cleanup_check(1))
return;
item = int_cleanup_item(cb);
if (item != NULL) {
if (sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item) <= 0)
OPENSSL_free(item);
}
}
/* The API function that performs all cleanup */
static void engine_cleanup_cb_free(ENGINE_CLEANUP_ITEM *item)
{
(*(item->cb)) ();
OPENSSL_free(item);
}
void engine_cleanup_int(void)
{
if (int_cleanup_check(0)) {
sk_ENGINE_CLEANUP_ITEM_pop_free(cleanup_stack,
engine_cleanup_cb_free);
cleanup_stack = NULL;
}
CRYPTO_THREAD_lock_free(global_engine_lock);
global_engine_lock = NULL;
}
/* Now the "ex_data" support */
int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg)
{
return CRYPTO_set_ex_data(&e->ex_data, idx, arg);
}
void *ENGINE_get_ex_data(const ENGINE *e, int idx)
{
return CRYPTO_get_ex_data(&e->ex_data, idx);
}
/*
* Functions to get/set an ENGINE's elements - mainly to avoid exposing the
* ENGINE structure itself.
*/
int ENGINE_set_id(ENGINE *e, const char *id)
{
if (id == NULL) {
ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
e->id = id;
return 1;
}
int ENGINE_set_name(ENGINE *e, const char *name)
{
if (name == NULL) {
ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
e->name = name;
return 1;
}
int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f)
{
e->destroy = destroy_f;
return 1;
}
int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f)
{
e->init = init_f;
return 1;
}
int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f)
{
e->finish = finish_f;
return 1;
}
int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f)
{
e->ctrl = ctrl_f;
return 1;
}
int ENGINE_set_flags(ENGINE *e, int flags)
{
e->flags = flags;
return 1;
}
int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns)
{
e->cmd_defns = defns;
return 1;
}
const char *ENGINE_get_id(const ENGINE *e)
{
return e->id;
}
const char *ENGINE_get_name(const ENGINE *e)
{
return e->name;
}
ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e)
{
return e->destroy;
}
ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e)
{
return e->init;
}
ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e)
{
return e->finish;
}
ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e)
{
return e->ctrl;
}
int ENGINE_get_flags(const ENGINE *e)
{
return e->flags;
}
const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e)
{
return e->cmd_defns;
}
/*
* eng_lib.o is pretty much linked into anything that touches ENGINE already,
* so put the "static_state" hack here.
*/
static int internal_static_hack = 0;
void *ENGINE_get_static_state(void)
{
return &internal_static_hack;
}
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 49e42550db1a..0cd8c4633aae 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -1,1707 +1,1711 @@
-# Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1999-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
#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_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_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_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_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_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/evp/ctrl_params_translate.c b/crypto/evp/ctrl_params_translate.c
index c767c316439d..ccafdfddd58f 100644
--- a/crypto/evp/ctrl_params_translate.c
+++ b/crypto/evp/ctrl_params_translate.c
@@ -1,2808 +1,2866 @@
/*
- * Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2021-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
*/
/*
* 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)
+ 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,
&ctx->sz);
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, 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;
}
}
}
/* 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(ctx->p2);
+ 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;
}
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;
}
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)
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)
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)
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) \
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) \
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) \
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_STRING, 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, 0, 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, 0, 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;
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.action_type = translation->action_type;
+ 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.
*/
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/evp/digest.c b/crypto/evp/digest.c
index e6e03eaf34a5..eefed523ec12 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -1,1108 +1,1108 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/* We need to use some engine deprecated APIs */
#define OPENSSL_SUPPRESS_DEPRECATED
#include <stdio.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#ifndef FIPS_MODULE
# include <openssl/engine.h>
#endif
#include <openssl/params.h>
#include <openssl/core_names.h>
#include "internal/cryptlib.h"
#include "internal/provider.h"
#include "internal/core.h"
#include "crypto/evp.h"
#include "evp_local.h"
static void cleanup_old_md_data(EVP_MD_CTX *ctx, int force)
{
if (ctx->digest != NULL) {
if (ctx->digest->cleanup != NULL
&& !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED))
ctx->digest->cleanup(ctx);
if (ctx->md_data != NULL && ctx->digest->ctx_size > 0
&& (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)
|| force)) {
OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
ctx->md_data = NULL;
}
}
}
void evp_md_ctx_clear_digest(EVP_MD_CTX *ctx, int force, int keep_fetched)
{
if (ctx->algctx != NULL) {
if (ctx->digest != NULL && ctx->digest->freectx != NULL)
ctx->digest->freectx(ctx->algctx);
ctx->algctx = NULL;
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
}
/* Code below to be removed when legacy support is dropped. */
/*
* Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because
* sometimes only copies of the context are ever finalised.
*/
cleanup_old_md_data(ctx, force);
if (force)
ctx->digest = NULL;
#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
ENGINE_finish(ctx->engine);
ctx->engine = NULL;
#endif
/* Non legacy code, this has to be later than the ctx->digest cleaning */
if (!keep_fetched) {
EVP_MD_free(ctx->fetched_digest);
ctx->fetched_digest = NULL;
ctx->reqdigest = NULL;
}
}
static int evp_md_ctx_reset_ex(EVP_MD_CTX *ctx, int keep_fetched)
{
if (ctx == NULL)
return 1;
#ifndef FIPS_MODULE
/*
* pctx should be freed by the user of EVP_MD_CTX
* if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set
*/
if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) {
EVP_PKEY_CTX_free(ctx->pctx);
ctx->pctx = NULL;
}
#endif
evp_md_ctx_clear_digest(ctx, 0, keep_fetched);
if (!keep_fetched)
OPENSSL_cleanse(ctx, sizeof(*ctx));
return 1;
}
/* This call frees resources associated with the context */
int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
{
return evp_md_ctx_reset_ex(ctx, 0);
}
#ifndef FIPS_MODULE
EVP_MD_CTX *evp_md_ctx_new_ex(EVP_PKEY *pkey, const ASN1_OCTET_STRING *id,
OSSL_LIB_CTX *libctx, const char *propq)
{
EVP_MD_CTX *ctx;
EVP_PKEY_CTX *pctx = NULL;
if ((ctx = EVP_MD_CTX_new()) == NULL
|| (pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq)) == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
if (id != NULL && EVP_PKEY_CTX_set1_id(pctx, id->data, id->length) <= 0)
goto err;
EVP_MD_CTX_set_pkey_ctx(ctx, pctx);
return ctx;
err:
EVP_PKEY_CTX_free(pctx);
EVP_MD_CTX_free(ctx);
return NULL;
}
#endif
EVP_MD_CTX *EVP_MD_CTX_new(void)
{
return OPENSSL_zalloc(sizeof(EVP_MD_CTX));
}
void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
{
if (ctx == NULL)
return;
EVP_MD_CTX_reset(ctx);
OPENSSL_free(ctx);
}
static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type,
const OSSL_PARAM params[], ENGINE *impl)
{
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
ENGINE *tmpimpl = NULL;
#endif
#if !defined(FIPS_MODULE)
if (ctx->pctx != NULL
&& EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx->pctx)
&& ctx->pctx->op.sig.algctx != NULL) {
/*
* Prior to OpenSSL 3.0 calling EVP_DigestInit_ex() on an mdctx
* previously initialised with EVP_DigestSignInit() would retain
* information about the key, and re-initialise for another sign
* operation. So in that case we redirect to EVP_DigestSignInit()
*/
if (ctx->pctx->operation == EVP_PKEY_OP_SIGNCTX)
return EVP_DigestSignInit(ctx, NULL, type, impl, NULL);
if (ctx->pctx->operation == EVP_PKEY_OP_VERIFYCTX)
return EVP_DigestVerifyInit(ctx, NULL, type, impl, NULL);
ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
return 0;
}
#endif
EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
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 (type != NULL) {
ctx->reqdigest = type;
} else {
if (ctx->digest == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_NO_DIGEST_SET);
return 0;
}
type = ctx->digest;
}
/* Code below to be removed when legacy support is dropped. */
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
/*
* Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
* this context may already have an ENGINE! Try to avoid releasing the
* previous handle, re-querying for an ENGINE, and having a
* reinitialisation, when it may all be unnecessary.
*/
if (ctx->engine && ctx->digest &&
(type == NULL || (type->type == ctx->digest->type)))
goto skip_to_init;
if (type != NULL) {
/*
* Ensure an ENGINE left lying around from last time is cleared (the
* previous check attempted to avoid this if the same ENGINE and
* EVP_MD could be used).
*/
ENGINE_finish(ctx->engine);
ctx->engine = NULL;
}
if (type != NULL && impl == NULL)
tmpimpl = ENGINE_get_digest_engine(type->type);
#endif
/*
* If there are engines involved or EVP_MD_CTX_FLAG_NO_INIT is set then we
* should use legacy handling for now.
*/
if (ctx->engine != NULL
|| impl != NULL
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
|| tmpimpl != NULL
#endif
|| (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0
|| (type != NULL && type->origin == EVP_ORIG_METH)
|| (type == NULL && ctx->digest != NULL
&& ctx->digest->origin == EVP_ORIG_METH)) {
if (ctx->digest == ctx->fetched_digest)
ctx->digest = NULL;
EVP_MD_free(ctx->fetched_digest);
ctx->fetched_digest = NULL;
goto legacy;
}
cleanup_old_md_data(ctx, 1);
/* Start of non-legacy code below */
if (type->prov == NULL) {
#ifdef FIPS_MODULE
/* We only do explicit fetches inside the FIPS module */
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
#else
/* The NULL digest is a special case */
EVP_MD *provmd = EVP_MD_fetch(NULL,
type->type != NID_undef ? OBJ_nid2sn(type->type)
: "NULL", "");
if (provmd == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
type = provmd;
EVP_MD_free(ctx->fetched_digest);
ctx->fetched_digest = provmd;
#endif
}
if (ctx->algctx != NULL && ctx->digest != NULL && ctx->digest != type) {
if (ctx->digest->freectx != NULL)
ctx->digest->freectx(ctx->algctx);
ctx->algctx = NULL;
}
if (type->prov != NULL && ctx->fetched_digest != type) {
if (!EVP_MD_up_ref((EVP_MD *)type)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
EVP_MD_free(ctx->fetched_digest);
ctx->fetched_digest = (EVP_MD *)type;
}
ctx->digest = type;
if (ctx->algctx == NULL) {
ctx->algctx = ctx->digest->newctx(ossl_provider_ctx(type->prov));
if (ctx->algctx == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
}
if (ctx->digest->dinit == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
return ctx->digest->dinit(ctx->algctx, params);
/* Code below to be removed when legacy support is dropped. */
legacy:
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
if (type) {
if (impl != NULL) {
if (!ENGINE_init(impl)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
} else {
/* Ask if an ENGINE is reserved for this job */
impl = tmpimpl;
}
if (impl != NULL) {
/* There's an ENGINE for this job ... (apparently) */
const EVP_MD *d = ENGINE_get_digest(impl, type->type);
if (d == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
ENGINE_finish(impl);
return 0;
}
/* We'll use the ENGINE's private digest definition */
type = d;
/*
* Store the ENGINE functional reference so we know 'type' came
* from an ENGINE and we need to release it when done.
*/
ctx->engine = impl;
} else
ctx->engine = NULL;
}
#endif
if (ctx->digest != type) {
cleanup_old_md_data(ctx, 1);
ctx->digest = type;
if (!(ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) && type->ctx_size) {
ctx->update = type->update;
ctx->md_data = OPENSSL_zalloc(type->ctx_size);
if (ctx->md_data == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
}
}
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
skip_to_init:
#endif
#ifndef FIPS_MODULE
if (ctx->pctx != NULL
&& (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx->pctx)
|| ctx->pctx->op.sig.signature == NULL)) {
int r;
r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_DIGESTINIT, 0, ctx);
if (r <= 0 && (r != -2))
return 0;
}
#endif
if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT)
return 1;
return ctx->digest->init(ctx);
}
int EVP_DigestInit_ex2(EVP_MD_CTX *ctx, const EVP_MD *type,
const OSSL_PARAM params[])
{
return evp_md_init_internal(ctx, type, params, NULL);
}
int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
{
EVP_MD_CTX_reset(ctx);
return evp_md_init_internal(ctx, type, NULL, NULL);
}
int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
{
return evp_md_init_internal(ctx, type, NULL, impl);
}
int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
{
if (count == 0)
return 1;
if (ctx->pctx != NULL
&& EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx->pctx)
&& ctx->pctx->op.sig.algctx != NULL) {
/*
* Prior to OpenSSL 3.0 EVP_DigestSignUpdate() and
* EVP_DigestVerifyUpdate() were just macros for EVP_DigestUpdate().
* Some code calls EVP_DigestUpdate() directly even when initialised
* with EVP_DigestSignInit_ex() or
* EVP_DigestVerifyInit_ex(), so we detect that and redirect to
* the correct EVP_Digest*Update() function
*/
if (ctx->pctx->operation == EVP_PKEY_OP_SIGNCTX)
return EVP_DigestSignUpdate(ctx, data, count);
if (ctx->pctx->operation == EVP_PKEY_OP_VERIFYCTX)
return EVP_DigestVerifyUpdate(ctx, data, count);
ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
return 0;
}
if (ctx->digest == NULL
|| ctx->digest->prov == NULL
|| (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0)
goto legacy;
if (ctx->digest->dupdate == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
return 0;
}
return ctx->digest->dupdate(ctx->algctx, data, count);
/* Code below to be removed when legacy support is dropped. */
legacy:
return ctx->update(ctx, data, count);
}
/* The caller can assume that this removes any secret data from the context */
int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
{
int ret;
ret = EVP_DigestFinal_ex(ctx, md, size);
EVP_MD_CTX_reset(ctx);
return ret;
}
/* The caller can assume that this removes any secret data from the context */
int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize)
{
int ret, sz;
size_t size = 0;
size_t mdsize = 0;
if (ctx->digest == NULL)
return 0;
sz = EVP_MD_get_size(ctx->digest);
if (sz < 0)
return 0;
mdsize = sz;
if (ctx->digest->prov == NULL)
goto legacy;
if (ctx->digest->dfinal == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
return 0;
}
ret = ctx->digest->dfinal(ctx->algctx, md, &size, mdsize);
if (isize != NULL) {
if (size <= UINT_MAX) {
- *isize = (int)size;
+ *isize = (unsigned int)size;
} else {
ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
ret = 0;
}
}
return ret;
/* Code below to be removed when legacy support is dropped. */
legacy:
OPENSSL_assert(mdsize <= EVP_MAX_MD_SIZE);
ret = ctx->digest->final(ctx, md);
if (isize != NULL)
*isize = mdsize;
if (ctx->digest->cleanup) {
ctx->digest->cleanup(ctx);
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
}
OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size);
return ret;
}
int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t size)
{
int ret = 0;
OSSL_PARAM params[2];
size_t i = 0;
if (ctx->digest == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_NULL_ALGORITHM);
return 0;
}
if (ctx->digest->prov == NULL)
goto legacy;
if (ctx->digest->dfinal == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
return 0;
}
params[i++] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_XOFLEN, &size);
params[i++] = OSSL_PARAM_construct_end();
if (EVP_MD_CTX_set_params(ctx, params) > 0)
ret = ctx->digest->dfinal(ctx->algctx, md, &size, size);
return ret;
legacy:
if (ctx->digest->flags & EVP_MD_FLAG_XOF
&& size <= INT_MAX
&& ctx->digest->md_ctrl(ctx, EVP_MD_CTRL_XOF_LEN, (int)size, NULL)) {
ret = ctx->digest->final(ctx, md);
if (ctx->digest->cleanup != NULL) {
ctx->digest->cleanup(ctx);
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
}
OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size);
} else {
ERR_raise(ERR_LIB_EVP, EVP_R_NOT_XOF_OR_INVALID_LENGTH);
}
return ret;
}
int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
{
EVP_MD_CTX_reset(out);
return EVP_MD_CTX_copy_ex(out, in);
}
int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
{
int digest_change = 0;
unsigned char *tmp_buf;
if (in == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (in->digest == NULL) {
/* copying uninitialized digest context */
EVP_MD_CTX_reset(out);
if (out->fetched_digest != NULL)
EVP_MD_free(out->fetched_digest);
*out = *in;
goto clone_pkey;
}
if (in->digest->prov == NULL
|| (in->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0)
goto legacy;
if (in->digest->dupctx == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX);
return 0;
}
evp_md_ctx_reset_ex(out, 1);
digest_change = (out->fetched_digest != in->fetched_digest);
if (digest_change && out->fetched_digest != NULL)
EVP_MD_free(out->fetched_digest);
*out = *in;
/* NULL out pointers in case of error */
out->pctx = NULL;
out->algctx = NULL;
if (digest_change && in->fetched_digest != NULL)
EVP_MD_up_ref(in->fetched_digest);
if (in->algctx != NULL) {
out->algctx = in->digest->dupctx(in->algctx);
if (out->algctx == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX);
return 0;
}
}
clone_pkey:
/* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */
EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
#ifndef FIPS_MODULE
if (in->pctx != NULL) {
out->pctx = EVP_PKEY_CTX_dup(in->pctx);
if (out->pctx == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX);
EVP_MD_CTX_reset(out);
return 0;
}
}
#endif
return 1;
/* Code below to be removed when legacy support is dropped. */
legacy:
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
/* Make sure it's safe to copy a digest context using an ENGINE */
if (in->engine && !ENGINE_init(in->engine)) {
ERR_raise(ERR_LIB_EVP, ERR_R_ENGINE_LIB);
return 0;
}
#endif
if (out->digest == in->digest) {
tmp_buf = out->md_data;
EVP_MD_CTX_set_flags(out, EVP_MD_CTX_FLAG_REUSE);
} else
tmp_buf = NULL;
EVP_MD_CTX_reset(out);
memcpy(out, in, sizeof(*out));
/* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */
EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
/* Null these variables, since they are getting fixed up
* properly below. Anything else may cause a memleak and/or
* double free if any of the memory allocations below fail
*/
out->md_data = NULL;
out->pctx = NULL;
if (in->md_data && out->digest->ctx_size) {
if (tmp_buf)
out->md_data = tmp_buf;
else {
out->md_data = OPENSSL_malloc(out->digest->ctx_size);
if (out->md_data == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
}
memcpy(out->md_data, in->md_data, out->digest->ctx_size);
}
out->update = in->update;
#ifndef FIPS_MODULE
if (in->pctx) {
out->pctx = EVP_PKEY_CTX_dup(in->pctx);
if (!out->pctx) {
EVP_MD_CTX_reset(out);
return 0;
}
}
#endif
if (out->digest->copy)
return out->digest->copy(out, in);
return 1;
}
int EVP_Digest(const void *data, size_t count,
unsigned char *md, unsigned int *size, const EVP_MD *type,
ENGINE *impl)
{
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
int ret;
if (ctx == NULL)
return 0;
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT);
ret = EVP_DigestInit_ex(ctx, type, impl)
&& EVP_DigestUpdate(ctx, data, count)
&& EVP_DigestFinal_ex(ctx, md, size);
EVP_MD_CTX_free(ctx);
return ret;
}
int EVP_Q_digest(OSSL_LIB_CTX *libctx, const char *name, const char *propq,
const void *data, size_t datalen,
unsigned char *md, size_t *mdlen)
{
EVP_MD *digest = EVP_MD_fetch(libctx, name, propq);
unsigned int temp = 0;
int ret = 0;
if (digest != NULL) {
ret = EVP_Digest(data, datalen, md, &temp, digest, NULL);
EVP_MD_free(digest);
}
if (mdlen != NULL)
*mdlen = temp;
return ret;
}
int EVP_MD_get_params(const EVP_MD *digest, OSSL_PARAM params[])
{
if (digest != NULL && digest->get_params != NULL)
return digest->get_params(params);
return 0;
}
const OSSL_PARAM *EVP_MD_gettable_params(const EVP_MD *digest)
{
if (digest != NULL && digest->gettable_params != NULL)
return digest->gettable_params(
ossl_provider_ctx(EVP_MD_get0_provider(digest)));
return NULL;
}
int EVP_MD_CTX_set_params(EVP_MD_CTX *ctx, const OSSL_PARAM params[])
{
EVP_PKEY_CTX *pctx = ctx->pctx;
/* If we have a pctx then we should try that first */
if (pctx != NULL
&& (pctx->operation == EVP_PKEY_OP_VERIFYCTX
|| pctx->operation == EVP_PKEY_OP_SIGNCTX)
&& pctx->op.sig.algctx != NULL
&& pctx->op.sig.signature->set_ctx_md_params != NULL)
return pctx->op.sig.signature->set_ctx_md_params(pctx->op.sig.algctx,
params);
if (ctx->digest != NULL && ctx->digest->set_ctx_params != NULL)
return ctx->digest->set_ctx_params(ctx->algctx, params);
return 0;
}
const OSSL_PARAM *EVP_MD_settable_ctx_params(const EVP_MD *md)
{
void *provctx;
if (md != NULL && md->settable_ctx_params != NULL) {
provctx = ossl_provider_ctx(EVP_MD_get0_provider(md));
return md->settable_ctx_params(NULL, provctx);
}
return NULL;
}
const OSSL_PARAM *EVP_MD_CTX_settable_params(EVP_MD_CTX *ctx)
{
EVP_PKEY_CTX *pctx;
void *alg;
if (ctx == NULL)
return NULL;
/* If we have a pctx then we should try that first */
pctx = ctx->pctx;
if (pctx != NULL
&& (pctx->operation == EVP_PKEY_OP_VERIFYCTX
|| pctx->operation == EVP_PKEY_OP_SIGNCTX)
&& pctx->op.sig.algctx != NULL
&& pctx->op.sig.signature->settable_ctx_md_params != NULL)
return pctx->op.sig.signature->settable_ctx_md_params(
pctx->op.sig.algctx);
if (ctx->digest != NULL && ctx->digest->settable_ctx_params != NULL) {
alg = ossl_provider_ctx(EVP_MD_get0_provider(ctx->digest));
return ctx->digest->settable_ctx_params(ctx->algctx, alg);
}
return NULL;
}
int EVP_MD_CTX_get_params(EVP_MD_CTX *ctx, OSSL_PARAM params[])
{
EVP_PKEY_CTX *pctx = ctx->pctx;
/* If we have a pctx then we should try that first */
if (pctx != NULL
&& (pctx->operation == EVP_PKEY_OP_VERIFYCTX
|| pctx->operation == EVP_PKEY_OP_SIGNCTX)
&& pctx->op.sig.algctx != NULL
&& pctx->op.sig.signature->get_ctx_md_params != NULL)
return pctx->op.sig.signature->get_ctx_md_params(pctx->op.sig.algctx,
params);
- if (ctx->digest != NULL && ctx->digest->get_params != NULL)
+ if (ctx->digest != NULL && ctx->digest->get_ctx_params != NULL)
return ctx->digest->get_ctx_params(ctx->algctx, params);
return 0;
}
const OSSL_PARAM *EVP_MD_gettable_ctx_params(const EVP_MD *md)
{
void *provctx;
if (md != NULL && md->gettable_ctx_params != NULL) {
provctx = ossl_provider_ctx(EVP_MD_get0_provider(md));
return md->gettable_ctx_params(NULL, provctx);
}
return NULL;
}
const OSSL_PARAM *EVP_MD_CTX_gettable_params(EVP_MD_CTX *ctx)
{
EVP_PKEY_CTX *pctx;
void *provctx;
if (ctx == NULL)
return NULL;
/* If we have a pctx then we should try that first */
pctx = ctx->pctx;
if (pctx != NULL
&& (pctx->operation == EVP_PKEY_OP_VERIFYCTX
|| pctx->operation == EVP_PKEY_OP_SIGNCTX)
&& pctx->op.sig.algctx != NULL
&& pctx->op.sig.signature->gettable_ctx_md_params != NULL)
return pctx->op.sig.signature->gettable_ctx_md_params(
pctx->op.sig.algctx);
if (ctx->digest != NULL && ctx->digest->gettable_ctx_params != NULL) {
provctx = ossl_provider_ctx(EVP_MD_get0_provider(ctx->digest));
return ctx->digest->gettable_ctx_params(ctx->algctx, provctx);
}
return NULL;
}
int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
{
int ret = EVP_CTRL_RET_UNSUPPORTED;
int set_params = 1;
size_t sz;
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
if (ctx == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (ctx->digest != NULL && ctx->digest->prov == NULL)
goto legacy;
switch (cmd) {
case EVP_MD_CTRL_XOF_LEN:
sz = (size_t)p1;
params[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_XOFLEN, &sz);
break;
case EVP_MD_CTRL_MICALG:
set_params = 0;
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_DIGEST_PARAM_MICALG,
p2, p1 ? p1 : 9999);
break;
case EVP_CTRL_SSL3_MASTER_SECRET:
params[0] = OSSL_PARAM_construct_octet_string(OSSL_DIGEST_PARAM_SSL3_MS,
p2, p1);
break;
default:
goto conclude;
}
if (set_params)
ret = EVP_MD_CTX_set_params(ctx, params);
else
ret = EVP_MD_CTX_get_params(ctx, params);
goto conclude;
/* Code below to be removed when legacy support is dropped. */
legacy:
if (ctx->digest->md_ctrl == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_CTRL_NOT_IMPLEMENTED);
return 0;
}
ret = ctx->digest->md_ctrl(ctx, cmd, p1, p2);
conclude:
if (ret <= 0)
return 0;
return ret;
}
EVP_MD *evp_md_new(void)
{
EVP_MD *md = OPENSSL_zalloc(sizeof(*md));
if (md != NULL) {
md->lock = CRYPTO_THREAD_lock_new();
if (md->lock == NULL) {
OPENSSL_free(md);
return NULL;
}
md->refcnt = 1;
}
return md;
}
/*
* FIPS module note: since internal fetches will be entirely
* provider based, we know that none of its code depends on legacy
* NIDs or any functionality that use them.
*/
#ifndef FIPS_MODULE
static void set_legacy_nid(const char *name, void *vlegacy_nid)
{
int nid;
int *legacy_nid = vlegacy_nid;
/*
* We use lowest level function to get the associated method, because
* higher level functions such as EVP_get_digestbyname() have changed
* to look at providers too.
*/
const void *legacy_method = OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH);
if (*legacy_nid == -1) /* We found a clash already */
return;
if (legacy_method == NULL)
return;
nid = EVP_MD_nid(legacy_method);
if (*legacy_nid != NID_undef && *legacy_nid != nid) {
*legacy_nid = -1;
return;
}
*legacy_nid = nid;
}
#endif
static int evp_md_cache_constants(EVP_MD *md)
{
int ok, xof = 0, algid_absent = 0;
size_t blksz = 0;
size_t mdsize = 0;
OSSL_PARAM params[5];
params[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_BLOCK_SIZE, &blksz);
params[1] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &mdsize);
params[2] = OSSL_PARAM_construct_int(OSSL_DIGEST_PARAM_XOF, &xof);
params[3] = OSSL_PARAM_construct_int(OSSL_DIGEST_PARAM_ALGID_ABSENT,
&algid_absent);
params[4] = OSSL_PARAM_construct_end();
ok = evp_do_md_getparams(md, params) > 0;
if (mdsize > INT_MAX || blksz > INT_MAX)
ok = 0;
if (ok) {
md->block_size = (int)blksz;
md->md_size = (int)mdsize;
if (xof)
md->flags |= EVP_MD_FLAG_XOF;
if (algid_absent)
md->flags |= EVP_MD_FLAG_DIGALGID_ABSENT;
}
return ok;
}
static void *evp_md_from_algorithm(int name_id,
const OSSL_ALGORITHM *algodef,
OSSL_PROVIDER *prov)
{
const OSSL_DISPATCH *fns = algodef->implementation;
EVP_MD *md = NULL;
int fncnt = 0;
/* EVP_MD_fetch() will set the legacy NID if available */
if ((md = evp_md_new()) == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return NULL;
}
#ifndef FIPS_MODULE
md->type = NID_undef;
if (!evp_names_do_all(prov, name_id, set_legacy_nid, &md->type)
|| md->type == -1) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
EVP_MD_free(md);
return NULL;
}
#endif
md->name_id = name_id;
if ((md->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
EVP_MD_free(md);
return NULL;
}
md->description = algodef->algorithm_description;
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
case OSSL_FUNC_DIGEST_NEWCTX:
if (md->newctx == NULL) {
md->newctx = OSSL_FUNC_digest_newctx(fns);
fncnt++;
}
break;
case OSSL_FUNC_DIGEST_INIT:
if (md->dinit == NULL) {
md->dinit = OSSL_FUNC_digest_init(fns);
fncnt++;
}
break;
case OSSL_FUNC_DIGEST_UPDATE:
if (md->dupdate == NULL) {
md->dupdate = OSSL_FUNC_digest_update(fns);
fncnt++;
}
break;
case OSSL_FUNC_DIGEST_FINAL:
if (md->dfinal == NULL) {
md->dfinal = OSSL_FUNC_digest_final(fns);
fncnt++;
}
break;
case OSSL_FUNC_DIGEST_DIGEST:
if (md->digest == NULL)
md->digest = OSSL_FUNC_digest_digest(fns);
/* We don't increment fnct for this as it is stand alone */
break;
case OSSL_FUNC_DIGEST_FREECTX:
if (md->freectx == NULL) {
md->freectx = OSSL_FUNC_digest_freectx(fns);
fncnt++;
}
break;
case OSSL_FUNC_DIGEST_DUPCTX:
if (md->dupctx == NULL)
md->dupctx = OSSL_FUNC_digest_dupctx(fns);
break;
case OSSL_FUNC_DIGEST_GET_PARAMS:
if (md->get_params == NULL)
md->get_params = OSSL_FUNC_digest_get_params(fns);
break;
case OSSL_FUNC_DIGEST_SET_CTX_PARAMS:
if (md->set_ctx_params == NULL)
md->set_ctx_params = OSSL_FUNC_digest_set_ctx_params(fns);
break;
case OSSL_FUNC_DIGEST_GET_CTX_PARAMS:
if (md->get_ctx_params == NULL)
md->get_ctx_params = OSSL_FUNC_digest_get_ctx_params(fns);
break;
case OSSL_FUNC_DIGEST_GETTABLE_PARAMS:
if (md->gettable_params == NULL)
md->gettable_params = OSSL_FUNC_digest_gettable_params(fns);
break;
case OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS:
if (md->settable_ctx_params == NULL)
md->settable_ctx_params =
OSSL_FUNC_digest_settable_ctx_params(fns);
break;
case OSSL_FUNC_DIGEST_GETTABLE_CTX_PARAMS:
if (md->gettable_ctx_params == NULL)
md->gettable_ctx_params =
OSSL_FUNC_digest_gettable_ctx_params(fns);
break;
}
}
if ((fncnt != 0 && fncnt != 5)
|| (fncnt == 0 && md->digest == NULL)) {
/*
* In order to be a consistent set of functions we either need the
* whole set of init/update/final etc functions or none of them.
* The "digest" function can standalone. We at least need one way to
* generate digests.
*/
EVP_MD_free(md);
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
return NULL;
}
md->prov = prov;
if (prov != NULL)
ossl_provider_up_ref(prov);
if (!evp_md_cache_constants(md)) {
EVP_MD_free(md);
ERR_raise(ERR_LIB_EVP, EVP_R_CACHE_CONSTANTS_FAILED);
md = NULL;
}
return md;
}
static int evp_md_up_ref(void *md)
{
return EVP_MD_up_ref(md);
}
static void evp_md_free(void *md)
{
EVP_MD_free(md);
}
EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
const char *properties)
{
EVP_MD *md =
evp_generic_fetch(ctx, OSSL_OP_DIGEST, algorithm, properties,
evp_md_from_algorithm, evp_md_up_ref, evp_md_free);
return md;
}
int EVP_MD_up_ref(EVP_MD *md)
{
int ref = 0;
if (md->origin == EVP_ORIG_DYNAMIC)
CRYPTO_UP_REF(&md->refcnt, &ref, md->lock);
return 1;
}
void EVP_MD_free(EVP_MD *md)
{
int i;
if (md == NULL || md->origin != EVP_ORIG_DYNAMIC)
return;
CRYPTO_DOWN_REF(&md->refcnt, &i, md->lock);
if (i > 0)
return;
evp_md_free_int(md);
}
void EVP_MD_do_all_provided(OSSL_LIB_CTX *libctx,
void (*fn)(EVP_MD *mac, void *arg),
void *arg)
{
evp_generic_do_all(libctx, OSSL_OP_DIGEST,
(void (*)(void *, void *))fn, arg,
evp_md_from_algorithm, evp_md_up_ref, evp_md_free);
}
diff --git a/crypto/evp/ec_ctrl.c b/crypto/evp/ec_ctrl.c
index 404358ab97f1..c1cf221a0db5 100644
--- a/crypto/evp/ec_ctrl.c
+++ b/crypto/evp/ec_ctrl.c
@@ -1,300 +1,302 @@
/*
- * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 "internal/deprecated.h"
#include <openssl/core_names.h>
#include <openssl/err.h>
#include <openssl/ec.h>
#include "crypto/evp.h"
#include "crypto/ec.h"
/*
* This file is meant to contain functions to provide EVP_PKEY support for EC
* keys.
*/
static ossl_inline
int evp_pkey_ctx_getset_ecdh_param_checks(const EVP_PKEY_CTX *ctx)
{
if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
/* If key type not EC return error */
if (evp_pkey_ctx_is_legacy(ctx)
&& ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_EC)
return -1;
return 1;
}
int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode)
{
int ret;
OSSL_PARAM params[2], *p = params;
ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
if (ret != 1)
return ret;
/*
* Valid input values are:
* * 0 for disable
* * 1 for enable
* * -1 for reset to default for associated priv key
*/
if (cofactor_mode < -1 || cofactor_mode > 1) {
/* Uses the same return value of pkey_ec_ctrl() */
return -2;
}
*p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
&cofactor_mode);
*p++ = OSSL_PARAM_construct_end();
ret = evp_pkey_ctx_set_params_strict(ctx, params);
if (ret == -2)
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return ret;
}
int EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx)
{
int ret, mode;
OSSL_PARAM params[2], *p = params;
ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
if (ret != 1)
return ret;
*p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
&mode);
*p++ = OSSL_PARAM_construct_end();
ret = evp_pkey_ctx_get_params_strict(ctx, params);
switch (ret) {
case -2:
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
break;
case 1:
ret = mode;
if (mode < 0 || mode > 1) {
/*
* The provider should return either 0 or 1, any other value is a
* provider error.
*/
ret = -1;
}
break;
default:
ret = -1;
break;
}
return ret;
}
/*
* This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
* simply because that's easier.
*/
int EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf)
{
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL);
}
/*
* This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
* simply because that's easier.
*/
int EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx)
{
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL);
}
/*
* This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
* simply because that's easier.
*/
int EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
{
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md));
}
/*
* This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
* simply because that's easier.
*/
int EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd)
{
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd));
}
int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int outlen)
{
int ret;
size_t len = outlen;
OSSL_PARAM params[2], *p = params;
ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
if (ret != 1)
return ret;
if (outlen <= 0) {
/*
* This would ideally be -1 or 0, but we have to retain compatibility
* with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if
* in <= 0
*/
return -2;
}
*p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
&len);
*p++ = OSSL_PARAM_construct_end();
ret = evp_pkey_ctx_set_params_strict(ctx, params);
if (ret == -2)
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return ret;
}
int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen)
{
size_t len = UINT_MAX;
int ret;
OSSL_PARAM params[2], *p = params;
ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
if (ret != 1)
return ret;
*p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
&len);
*p++ = OSSL_PARAM_construct_end();
ret = evp_pkey_ctx_get_params_strict(ctx, params);
switch (ret) {
case -2:
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
break;
case 1:
if (len <= INT_MAX)
*plen = (int)len;
else
ret = -1;
break;
default:
ret = -1;
break;
}
return ret;
}
int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len)
{
int ret;
OSSL_PARAM params[2], *p = params;
ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
if (ret != 1)
return ret;
*p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
/*
* Cast away the const. This is read
* only so should be safe
*/
(void *)ukm,
(size_t)len);
*p++ = OSSL_PARAM_construct_end();
ret = evp_pkey_ctx_set_params_strict(ctx, params);
switch (ret) {
case -2:
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
break;
case 1:
OPENSSL_free(ukm);
break;
}
return ret;
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
{
size_t ukmlen;
int ret;
OSSL_PARAM params[2], *p = params;
ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
if (ret != 1)
return ret;
*p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM,
(void **)pukm, 0);
*p++ = OSSL_PARAM_construct_end();
ret = evp_pkey_ctx_get_params_strict(ctx, params);
switch (ret) {
case -2:
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
break;
case 1:
ret = -1;
ukmlen = params[0].return_size;
if (ukmlen <= INT_MAX)
ret = (int)ukmlen;
break;
default:
ret = -1;
break;
}
return ret;
}
#endif
#ifndef FIPS_MODULE
/*
* This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
* simply because that's easier.
* ASN1_OBJECT (which would be converted to text internally)?
*/
int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid)
{
- return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_TYPE_GEN,
+ int keytype = nid == EVP_PKEY_SM2 ? EVP_PKEY_SM2 : EVP_PKEY_EC;
+
+ return EVP_PKEY_CTX_ctrl(ctx, keytype, EVP_PKEY_OP_TYPE_GEN,
EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID,
nid, NULL);
}
/*
* This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
* simply because that's easier.
*/
int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc)
{
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_TYPE_GEN,
EVP_PKEY_CTRL_EC_PARAM_ENC, param_enc, NULL);
}
#endif
diff --git a/crypto/evp/evp_pbe.c b/crypto/evp/evp_pbe.c
index 5f6720d2c3f3..56ee69865c9e 100644
--- a/crypto/evp/evp_pbe.c
+++ b/crypto/evp/evp_pbe.c
@@ -1,302 +1,302 @@
/*
- * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-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/evp.h>
#include <openssl/core.h>
#include <openssl/core_names.h>
#include <openssl/pkcs12.h>
#include <openssl/x509.h>
#include "crypto/evp.h"
#include "evp_local.h"
/* Password based encryption (PBE) functions */
/* Setup a cipher context from a PBE algorithm */
struct evp_pbe_st {
int pbe_type;
int pbe_nid;
int cipher_nid;
int md_nid;
EVP_PBE_KEYGEN *keygen;
EVP_PBE_KEYGEN_EX *keygen_ex;
};
static STACK_OF(EVP_PBE_CTL) *pbe_algs;
static const EVP_PBE_CTL builtin_pbe[] = {
{EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndDES_CBC,
NID_des_cbc, NID_md2, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndDES_CBC,
NID_des_cbc, NID_md5, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndRC2_CBC,
NID_rc2_64_cbc, NID_sha1, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen},
{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC4,
NID_rc4, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC4,
NID_rc4_40, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
NID_des_ede3_cbc, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And2_Key_TripleDES_CBC,
NID_des_ede_cbc, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC2_CBC,
NID_rc2_cbc, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC2_CBC,
NID_rc2_40_cbc, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbes2, -1, -1, PKCS5_v2_PBE_keyivgen, &PKCS5_v2_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndRC2_CBC,
NID_rc2_64_cbc, NID_md2, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndRC2_CBC,
NID_rc2_64_cbc, NID_md5, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndDES_CBC,
NID_des_cbc, NID_sha1, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_PRF, NID_hmacWithSHA1, -1, NID_sha1, 0},
{EVP_PBE_TYPE_PRF, NID_hmac_md5, -1, NID_md5, 0},
{EVP_PBE_TYPE_PRF, NID_hmac_sha1, -1, NID_sha1, 0},
{EVP_PBE_TYPE_PRF, NID_hmacWithMD5, -1, NID_md5, 0},
{EVP_PBE_TYPE_PRF, NID_hmacWithSHA224, -1, NID_sha224, 0},
{EVP_PBE_TYPE_PRF, NID_hmacWithSHA256, -1, NID_sha256, 0},
{EVP_PBE_TYPE_PRF, NID_hmacWithSHA384, -1, NID_sha384, 0},
{EVP_PBE_TYPE_PRF, NID_hmacWithSHA512, -1, NID_sha512, 0},
{EVP_PBE_TYPE_PRF, NID_id_HMACGostR3411_94, -1, NID_id_GostR3411_94, 0},
{EVP_PBE_TYPE_PRF, NID_id_tc26_hmac_gost_3411_2012_256, -1,
NID_id_GostR3411_2012_256, 0},
{EVP_PBE_TYPE_PRF, NID_id_tc26_hmac_gost_3411_2012_512, -1,
NID_id_GostR3411_2012_512, 0},
{EVP_PBE_TYPE_PRF, NID_hmacWithSHA512_224, -1, NID_sha512_224, 0},
{EVP_PBE_TYPE_PRF, NID_hmacWithSHA512_256, -1, NID_sha512_256, 0},
{EVP_PBE_TYPE_KDF, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen, &PKCS5_v2_PBKDF2_keyivgen_ex},
#ifndef OPENSSL_NO_SCRYPT
{EVP_PBE_TYPE_KDF, NID_id_scrypt, -1, -1, PKCS5_v2_scrypt_keyivgen, &PKCS5_v2_scrypt_keyivgen_ex}
#endif
};
int EVP_PBE_CipherInit_ex(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de,
OSSL_LIB_CTX *libctx, const char *propq)
{
const EVP_CIPHER *cipher = NULL;
EVP_CIPHER *cipher_fetch = NULL;
const EVP_MD *md = NULL;
EVP_MD *md_fetch = NULL;
int ret = 0, cipher_nid, md_nid;
EVP_PBE_KEYGEN_EX *keygen_ex;
EVP_PBE_KEYGEN *keygen;
if (!EVP_PBE_find_ex(EVP_PBE_TYPE_OUTER, OBJ_obj2nid(pbe_obj),
&cipher_nid, &md_nid, &keygen, &keygen_ex)) {
char obj_tmp[80];
if (pbe_obj == NULL)
OPENSSL_strlcpy(obj_tmp, "NULL", sizeof(obj_tmp));
else
i2t_ASN1_OBJECT(obj_tmp, sizeof(obj_tmp), pbe_obj);
ERR_raise_data(ERR_LIB_EVP, EVP_R_UNKNOWN_PBE_ALGORITHM,
"TYPE=%s", obj_tmp);
goto err;
}
if (pass == NULL)
passlen = 0;
else if (passlen == -1)
passlen = strlen(pass);
if (cipher_nid != -1) {
(void)ERR_set_mark();
cipher = cipher_fetch = EVP_CIPHER_fetch(libctx, OBJ_nid2sn(cipher_nid), propq);
/* Fallback to legacy method */
if (cipher == NULL)
cipher = EVP_get_cipherbynid(cipher_nid);
if (cipher == NULL) {
(void)ERR_clear_last_mark();
ERR_raise_data(ERR_LIB_EVP, EVP_R_UNKNOWN_CIPHER,
OBJ_nid2sn(cipher_nid));
goto err;
}
(void)ERR_pop_to_mark();
}
if (md_nid != -1) {
(void)ERR_set_mark();
md = md_fetch = EVP_MD_fetch(libctx, OBJ_nid2sn(md_nid), propq);
/* Fallback to legacy method */
if (md == NULL)
- EVP_get_digestbynid(md_nid);
+ md = EVP_get_digestbynid(md_nid);
if (md == NULL) {
(void)ERR_clear_last_mark();
ERR_raise(ERR_LIB_EVP, EVP_R_UNKNOWN_DIGEST);
goto err;
}
(void)ERR_pop_to_mark();
}
/* Try extended keygen with libctx/propq first, fall back to legacy keygen */
if (keygen_ex != NULL)
ret = keygen_ex(ctx, pass, passlen, param, cipher, md, en_de, libctx, propq);
else
ret = keygen(ctx, pass, passlen, param, cipher, md, en_de);
err:
EVP_CIPHER_free(cipher_fetch);
EVP_MD_free(md_fetch);
return ret;
}
int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de)
{
return EVP_PBE_CipherInit_ex(pbe_obj, pass, passlen, param, ctx, en_de, NULL, NULL);
}
DECLARE_OBJ_BSEARCH_CMP_FN(EVP_PBE_CTL, EVP_PBE_CTL, pbe2);
static int pbe2_cmp(const EVP_PBE_CTL *pbe1, const EVP_PBE_CTL *pbe2)
{
int ret = pbe1->pbe_type - pbe2->pbe_type;
if (ret)
return ret;
else
return pbe1->pbe_nid - pbe2->pbe_nid;
}
IMPLEMENT_OBJ_BSEARCH_CMP_FN(EVP_PBE_CTL, EVP_PBE_CTL, pbe2);
static int pbe_cmp(const EVP_PBE_CTL *const *a, const EVP_PBE_CTL *const *b)
{
int ret = (*a)->pbe_type - (*b)->pbe_type;
if (ret)
return ret;
else
return (*a)->pbe_nid - (*b)->pbe_nid;
}
/* Add a PBE algorithm */
int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid,
int md_nid, EVP_PBE_KEYGEN *keygen)
{
EVP_PBE_CTL *pbe_tmp;
if (pbe_algs == NULL) {
pbe_algs = sk_EVP_PBE_CTL_new(pbe_cmp);
if (pbe_algs == NULL)
goto err;
}
if ((pbe_tmp = OPENSSL_zalloc(sizeof(*pbe_tmp))) == NULL)
goto err;
pbe_tmp->pbe_type = pbe_type;
pbe_tmp->pbe_nid = pbe_nid;
pbe_tmp->cipher_nid = cipher_nid;
pbe_tmp->md_nid = md_nid;
pbe_tmp->keygen = keygen;
if (!sk_EVP_PBE_CTL_push(pbe_algs, pbe_tmp)) {
OPENSSL_free(pbe_tmp);
goto err;
}
return 1;
err:
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
EVP_PBE_KEYGEN *keygen)
{
int cipher_nid, md_nid;
if (cipher)
cipher_nid = EVP_CIPHER_get_nid(cipher);
else
cipher_nid = -1;
if (md)
md_nid = EVP_MD_get_type(md);
else
md_nid = -1;
return EVP_PBE_alg_add_type(EVP_PBE_TYPE_OUTER, nid,
cipher_nid, md_nid, keygen);
}
int EVP_PBE_find_ex(int type, int pbe_nid, int *pcnid, int *pmnid,
EVP_PBE_KEYGEN **pkeygen, EVP_PBE_KEYGEN_EX **pkeygen_ex)
{
EVP_PBE_CTL *pbetmp = NULL, pbelu;
int i;
if (pbe_nid == NID_undef)
return 0;
pbelu.pbe_type = type;
pbelu.pbe_nid = pbe_nid;
if (pbe_algs != NULL) {
i = sk_EVP_PBE_CTL_find(pbe_algs, &pbelu);
pbetmp = sk_EVP_PBE_CTL_value(pbe_algs, i);
}
if (pbetmp == NULL) {
pbetmp = OBJ_bsearch_pbe2(&pbelu, builtin_pbe, OSSL_NELEM(builtin_pbe));
}
if (pbetmp == NULL)
return 0;
if (pcnid != NULL)
*pcnid = pbetmp->cipher_nid;
if (pmnid != NULL)
*pmnid = pbetmp->md_nid;
if (pkeygen != NULL)
*pkeygen = pbetmp->keygen;
if (pkeygen_ex != NULL)
*pkeygen_ex = pbetmp->keygen_ex;
return 1;
}
int EVP_PBE_find(int type, int pbe_nid,
int *pcnid, int *pmnid, EVP_PBE_KEYGEN **pkeygen)
{
return EVP_PBE_find_ex(type, pbe_nid, pcnid, pmnid, pkeygen, NULL);
}
static void free_evp_pbe_ctl(EVP_PBE_CTL *pbe)
{
OPENSSL_free(pbe);
}
void EVP_PBE_cleanup(void)
{
sk_EVP_PBE_CTL_pop_free(pbe_algs, free_evp_pbe_ctl);
pbe_algs = NULL;
}
int EVP_PBE_get(int *ptype, int *ppbe_nid, size_t num)
{
const EVP_PBE_CTL *tpbe;
if (num >= OSSL_NELEM(builtin_pbe))
return 0;
tpbe = builtin_pbe + num;
if (ptype)
*ptype = tpbe->pbe_type;
if (ppbe_nid)
*ppbe_nid = tpbe->pbe_nid;
return 1;
}
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
index 90fd8068dc42..b1e8870e36ac 100644
--- a/crypto/evp/keymgmt_meth.c
+++ b/crypto/evp/keymgmt_meth.c
@@ -1,496 +1,496 @@
/*
- * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <openssl/crypto.h>
#include <openssl/core_dispatch.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include "internal/provider.h"
#include "internal/refcount.h"
#include "internal/core.h"
#include "crypto/evp.h"
#include "evp_local.h"
static void *keymgmt_new(void)
{
EVP_KEYMGMT *keymgmt = NULL;
if ((keymgmt = OPENSSL_zalloc(sizeof(*keymgmt))) == NULL
|| (keymgmt->lock = CRYPTO_THREAD_lock_new()) == NULL) {
EVP_KEYMGMT_free(keymgmt);
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return NULL;
}
keymgmt->refcnt = 1;
return keymgmt;
}
static void *keymgmt_from_algorithm(int name_id,
const OSSL_ALGORITHM *algodef,
OSSL_PROVIDER *prov)
{
const OSSL_DISPATCH *fns = algodef->implementation;
EVP_KEYMGMT *keymgmt = NULL;
int setparamfncnt = 0, getparamfncnt = 0;
int setgenparamfncnt = 0;
int importfncnt = 0, exportfncnt = 0;
if ((keymgmt = keymgmt_new()) == NULL)
return NULL;
keymgmt->name_id = name_id;
if ((keymgmt->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
EVP_KEYMGMT_free(keymgmt);
return NULL;
}
keymgmt->description = algodef->algorithm_description;
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
case OSSL_FUNC_KEYMGMT_NEW:
if (keymgmt->new == NULL)
keymgmt->new = OSSL_FUNC_keymgmt_new(fns);
break;
case OSSL_FUNC_KEYMGMT_GEN_INIT:
if (keymgmt->gen_init == NULL)
keymgmt->gen_init = OSSL_FUNC_keymgmt_gen_init(fns);
break;
case OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE:
if (keymgmt->gen_set_template == NULL)
keymgmt->gen_set_template =
OSSL_FUNC_keymgmt_gen_set_template(fns);
break;
case OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS:
if (keymgmt->gen_set_params == NULL) {
setgenparamfncnt++;
keymgmt->gen_set_params =
OSSL_FUNC_keymgmt_gen_set_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS:
if (keymgmt->gen_settable_params == NULL) {
setgenparamfncnt++;
keymgmt->gen_settable_params =
OSSL_FUNC_keymgmt_gen_settable_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_GEN:
if (keymgmt->gen == NULL)
keymgmt->gen = OSSL_FUNC_keymgmt_gen(fns);
break;
case OSSL_FUNC_KEYMGMT_GEN_CLEANUP:
if (keymgmt->gen_cleanup == NULL)
keymgmt->gen_cleanup = OSSL_FUNC_keymgmt_gen_cleanup(fns);
break;
case OSSL_FUNC_KEYMGMT_FREE:
if (keymgmt->free == NULL)
keymgmt->free = OSSL_FUNC_keymgmt_free(fns);
break;
case OSSL_FUNC_KEYMGMT_LOAD:
if (keymgmt->load == NULL)
keymgmt->load = OSSL_FUNC_keymgmt_load(fns);
break;
case OSSL_FUNC_KEYMGMT_GET_PARAMS:
if (keymgmt->get_params == NULL) {
getparamfncnt++;
keymgmt->get_params = OSSL_FUNC_keymgmt_get_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS:
if (keymgmt->gettable_params == NULL) {
getparamfncnt++;
keymgmt->gettable_params =
OSSL_FUNC_keymgmt_gettable_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_SET_PARAMS:
if (keymgmt->set_params == NULL) {
setparamfncnt++;
keymgmt->set_params = OSSL_FUNC_keymgmt_set_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS:
if (keymgmt->settable_params == NULL) {
setparamfncnt++;
keymgmt->settable_params =
OSSL_FUNC_keymgmt_settable_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME:
if (keymgmt->query_operation_name == NULL)
keymgmt->query_operation_name =
OSSL_FUNC_keymgmt_query_operation_name(fns);
break;
case OSSL_FUNC_KEYMGMT_HAS:
if (keymgmt->has == NULL)
keymgmt->has = OSSL_FUNC_keymgmt_has(fns);
break;
case OSSL_FUNC_KEYMGMT_DUP:
if (keymgmt->dup == NULL)
keymgmt->dup = OSSL_FUNC_keymgmt_dup(fns);
break;
case OSSL_FUNC_KEYMGMT_VALIDATE:
if (keymgmt->validate == NULL)
keymgmt->validate = OSSL_FUNC_keymgmt_validate(fns);
break;
case OSSL_FUNC_KEYMGMT_MATCH:
if (keymgmt->match == NULL)
keymgmt->match = OSSL_FUNC_keymgmt_match(fns);
break;
case OSSL_FUNC_KEYMGMT_IMPORT:
if (keymgmt->import == NULL) {
importfncnt++;
keymgmt->import = OSSL_FUNC_keymgmt_import(fns);
}
break;
case OSSL_FUNC_KEYMGMT_IMPORT_TYPES:
if (keymgmt->import_types == NULL) {
importfncnt++;
keymgmt->import_types = OSSL_FUNC_keymgmt_import_types(fns);
}
break;
case OSSL_FUNC_KEYMGMT_EXPORT:
if (keymgmt->export == NULL) {
exportfncnt++;
keymgmt->export = OSSL_FUNC_keymgmt_export(fns);
}
break;
case OSSL_FUNC_KEYMGMT_EXPORT_TYPES:
if (keymgmt->export_types == NULL) {
exportfncnt++;
keymgmt->export_types = OSSL_FUNC_keymgmt_export_types(fns);
}
break;
}
}
/*
* Try to check that the method is sensible.
* At least one constructor and the destructor are MANDATORY
* The functions 'has' is MANDATORY
* It makes no sense being able to free stuff if you can't create it.
* It makes no sense providing OSSL_PARAM descriptors for import and
* export if you can't import or export.
*/
if (keymgmt->free == NULL
|| (keymgmt->new == NULL
&& keymgmt->gen == NULL
&& keymgmt->load == NULL)
|| keymgmt->has == NULL
|| (getparamfncnt != 0 && getparamfncnt != 2)
|| (setparamfncnt != 0 && setparamfncnt != 2)
|| (setgenparamfncnt != 0 && setgenparamfncnt != 2)
|| (importfncnt != 0 && importfncnt != 2)
|| (exportfncnt != 0 && exportfncnt != 2)
|| (keymgmt->gen != NULL
&& (keymgmt->gen_init == NULL
|| keymgmt->gen_cleanup == NULL))) {
EVP_KEYMGMT_free(keymgmt);
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
return NULL;
}
keymgmt->prov = prov;
if (prov != NULL)
ossl_provider_up_ref(prov);
return keymgmt;
}
EVP_KEYMGMT *evp_keymgmt_fetch_by_number(OSSL_LIB_CTX *ctx, int name_id,
const char *properties)
{
return evp_generic_fetch_by_number(ctx,
OSSL_OP_KEYMGMT, name_id, properties,
keymgmt_from_algorithm,
(int (*)(void *))EVP_KEYMGMT_up_ref,
(void (*)(void *))EVP_KEYMGMT_free);
}
EVP_KEYMGMT *evp_keymgmt_fetch_from_prov(OSSL_PROVIDER *prov,
const char *name,
const char *properties)
{
return evp_generic_fetch_from_prov(prov, OSSL_OP_KEYMGMT,
name, properties,
keymgmt_from_algorithm,
(int (*)(void *))EVP_KEYMGMT_up_ref,
(void (*)(void *))EVP_KEYMGMT_free);
}
EVP_KEYMGMT *EVP_KEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
const char *properties)
{
return evp_generic_fetch(ctx, OSSL_OP_KEYMGMT, algorithm, properties,
keymgmt_from_algorithm,
(int (*)(void *))EVP_KEYMGMT_up_ref,
(void (*)(void *))EVP_KEYMGMT_free);
}
int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt)
{
int ref = 0;
CRYPTO_UP_REF(&keymgmt->refcnt, &ref, keymgmt->lock);
return 1;
}
void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt)
{
int ref = 0;
if (keymgmt == NULL)
return;
CRYPTO_DOWN_REF(&keymgmt->refcnt, &ref, keymgmt->lock);
if (ref > 0)
return;
OPENSSL_free(keymgmt->type_name);
ossl_provider_free(keymgmt->prov);
CRYPTO_THREAD_lock_free(keymgmt->lock);
OPENSSL_free(keymgmt);
}
const OSSL_PROVIDER *EVP_KEYMGMT_get0_provider(const EVP_KEYMGMT *keymgmt)
{
return keymgmt->prov;
}
int evp_keymgmt_get_number(const EVP_KEYMGMT *keymgmt)
{
return keymgmt->name_id;
}
const char *EVP_KEYMGMT_get0_description(const EVP_KEYMGMT *keymgmt)
{
return keymgmt->description;
}
const char *EVP_KEYMGMT_get0_name(const EVP_KEYMGMT *keymgmt)
{
return keymgmt->type_name;
}
int EVP_KEYMGMT_is_a(const EVP_KEYMGMT *keymgmt, const char *name)
{
return keymgmt != NULL
&& evp_is_a(keymgmt->prov, keymgmt->name_id, NULL, name);
}
void EVP_KEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx,
void (*fn)(EVP_KEYMGMT *keymgmt, void *arg),
void *arg)
{
evp_generic_do_all(libctx, OSSL_OP_KEYMGMT,
(void (*)(void *, void *))fn, arg,
keymgmt_from_algorithm,
(int (*)(void *))EVP_KEYMGMT_up_ref,
(void (*)(void *))EVP_KEYMGMT_free);
}
int EVP_KEYMGMT_names_do_all(const EVP_KEYMGMT *keymgmt,
void (*fn)(const char *name, void *data),
void *data)
{
if (keymgmt->prov != NULL)
return evp_names_do_all(keymgmt->prov, keymgmt->name_id, fn, data);
return 1;
}
/*
* Internal API that interfaces with the method function pointers
*/
void *evp_keymgmt_newdata(const EVP_KEYMGMT *keymgmt)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
/*
* 'new' is currently mandatory on its own, but when new
* constructors appear, it won't be quite as mandatory,
* so we have a check for future cases.
*/
if (keymgmt->new == NULL)
return NULL;
return keymgmt->new(provctx);
}
void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keydata)
{
/* This is mandatory, no need to check for its presence */
keymgmt->free(keydata);
}
void *evp_keymgmt_gen_init(const EVP_KEYMGMT *keymgmt, int selection,
const OSSL_PARAM params[])
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
if (keymgmt->gen_init == NULL)
return NULL;
return keymgmt->gen_init(provctx, selection, params);
}
int evp_keymgmt_gen_set_template(const EVP_KEYMGMT *keymgmt, void *genctx,
void *template)
{
/*
* It's arguable if we actually should return success in this case, as
* it allows the caller to set a template key, which is then ignored.
* However, this is how the legacy methods (EVP_PKEY_METHOD) operate,
* so we do this in the interest of backward compatibility.
*/
if (keymgmt->gen_set_template == NULL)
return 1;
return keymgmt->gen_set_template(genctx, template);
}
int evp_keymgmt_gen_set_params(const EVP_KEYMGMT *keymgmt, void *genctx,
const OSSL_PARAM params[])
{
if (keymgmt->gen_set_params == NULL)
return 0;
return keymgmt->gen_set_params(genctx, params);
}
const OSSL_PARAM *EVP_KEYMGMT_gen_settable_params(const EVP_KEYMGMT *keymgmt)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
if (keymgmt->gen_settable_params == NULL)
return NULL;
return keymgmt->gen_settable_params(NULL, provctx);
}
void *evp_keymgmt_gen(const EVP_KEYMGMT *keymgmt, void *genctx,
OSSL_CALLBACK *cb, void *cbarg)
{
if (keymgmt->gen == NULL)
return NULL;
return keymgmt->gen(genctx, cb, cbarg);
}
void evp_keymgmt_gen_cleanup(const EVP_KEYMGMT *keymgmt, void *genctx)
{
- if (keymgmt->gen != NULL)
+ if (keymgmt->gen_cleanup != NULL)
keymgmt->gen_cleanup(genctx);
}
int evp_keymgmt_has_load(const EVP_KEYMGMT *keymgmt)
{
return keymgmt != NULL && keymgmt->load != NULL;
}
void *evp_keymgmt_load(const EVP_KEYMGMT *keymgmt,
const void *objref, size_t objref_sz)
{
if (evp_keymgmt_has_load(keymgmt))
return keymgmt->load(objref, objref_sz);
return NULL;
}
int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt, void *keydata,
OSSL_PARAM params[])
{
if (keymgmt->get_params == NULL)
return 1;
return keymgmt->get_params(keydata, params);
}
const OSSL_PARAM *EVP_KEYMGMT_gettable_params(const EVP_KEYMGMT *keymgmt)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
if (keymgmt->gettable_params == NULL)
return NULL;
return keymgmt->gettable_params(provctx);
}
int evp_keymgmt_set_params(const EVP_KEYMGMT *keymgmt, void *keydata,
const OSSL_PARAM params[])
{
if (keymgmt->set_params == NULL)
return 1;
return keymgmt->set_params(keydata, params);
}
const OSSL_PARAM *EVP_KEYMGMT_settable_params(const EVP_KEYMGMT *keymgmt)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
if (keymgmt->settable_params == NULL)
return NULL;
return keymgmt->settable_params(provctx);
}
int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keydata, int selection)
{
/* This is mandatory, no need to check for its presence */
return keymgmt->has(keydata, selection);
}
int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata,
int selection, int checktype)
{
/* We assume valid if the implementation doesn't have a function */
if (keymgmt->validate == NULL)
return 1;
return keymgmt->validate(keydata, selection, checktype);
}
int evp_keymgmt_match(const EVP_KEYMGMT *keymgmt,
const void *keydata1, const void *keydata2,
int selection)
{
/* We assume no match if the implementation doesn't have a function */
if (keymgmt->match == NULL)
return 0;
return keymgmt->match(keydata1, keydata2, selection);
}
int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata,
int selection, const OSSL_PARAM params[])
{
if (keymgmt->import == NULL)
return 0;
return keymgmt->import(keydata, selection, params);
}
const OSSL_PARAM *evp_keymgmt_import_types(const EVP_KEYMGMT *keymgmt,
int selection)
{
if (keymgmt->import_types == NULL)
return NULL;
return keymgmt->import_types(selection);
}
int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata,
int selection, OSSL_CALLBACK *param_cb, void *cbarg)
{
if (keymgmt->export == NULL)
return 0;
return keymgmt->export(keydata, selection, param_cb, cbarg);
}
const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
int selection)
{
if (keymgmt->export_types == NULL)
return NULL;
return keymgmt->export_types(selection);
}
void *evp_keymgmt_dup(const EVP_KEYMGMT *keymgmt, const void *keydata_from,
int selection)
{
/* We assume no dup if the implementation doesn't have a function */
if (keymgmt->dup == NULL)
return NULL;
return keymgmt->dup(keydata_from, selection);
}
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 5803974c3221..f6acb5b47eff 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -1,2460 +1,2473 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/*
* DSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <assert.h>
#include <stdio.h>
#include "internal/cryptlib.h"
#include "internal/refcount.h"
#include "internal/namemap.h"
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/dh.h>
#include <openssl/ec.h>
#include <openssl/cmac.h>
#ifndef FIPS_MODULE
# include <openssl/engine.h>
#endif
#include <openssl/params.h>
#include <openssl/param_build.h>
#include <openssl/encoder.h>
#include <openssl/core_names.h>
#include "internal/numbers.h" /* includes SIZE_MAX */
#include "internal/ffc.h"
#include "crypto/evp.h"
#include "crypto/dh.h"
#include "crypto/dsa.h"
#include "crypto/ec.h"
#include "crypto/ecx.h"
#include "crypto/rsa.h"
#ifndef FIPS_MODULE
# include "crypto/asn1.h"
# include "crypto/x509.h"
#endif
#include "internal/provider.h"
#include "evp_local.h"
static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
int len, EVP_KEYMGMT *keymgmt);
static void evp_pkey_free_it(EVP_PKEY *key);
#ifndef FIPS_MODULE
/* The type of parameters selected in key parameter functions */
# define SELECT_PARAMETERS OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
int EVP_PKEY_get_bits(const EVP_PKEY *pkey)
{
int size = 0;
if (pkey != NULL) {
size = pkey->cache.bits;
if (pkey->ameth != NULL && pkey->ameth->pkey_bits != NULL)
size = pkey->ameth->pkey_bits(pkey);
}
return size < 0 ? 0 : size;
}
int EVP_PKEY_get_security_bits(const EVP_PKEY *pkey)
{
int size = 0;
if (pkey != NULL) {
size = pkey->cache.security_bits;
if (pkey->ameth != NULL && pkey->ameth->pkey_security_bits != NULL)
size = pkey->ameth->pkey_security_bits(pkey);
}
return size < 0 ? 0 : size;
}
int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
{
# ifndef OPENSSL_NO_DSA
if (pkey->type == EVP_PKEY_DSA) {
int ret = pkey->save_parameters;
if (mode >= 0)
pkey->save_parameters = mode;
return ret;
}
# endif
# ifndef OPENSSL_NO_EC
if (pkey->type == EVP_PKEY_EC) {
int ret = pkey->save_parameters;
if (mode >= 0)
pkey->save_parameters = mode;
return ret;
}
# endif
return 0;
}
int EVP_PKEY_set_ex_data(EVP_PKEY *key, int idx, void *arg)
{
return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
}
void *EVP_PKEY_get_ex_data(const EVP_PKEY *key, int idx)
{
return CRYPTO_get_ex_data(&key->ex_data, idx);
}
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
{
/*
* Clean up legacy stuff from this function when legacy support is gone.
*/
EVP_PKEY *downgraded_from = NULL;
int ok = 0;
/*
* If |to| is a legacy key and |from| isn't, we must make a downgraded
* copy of |from|. If that fails, this function fails.
*/
if (evp_pkey_is_legacy(to) && evp_pkey_is_provided(from)) {
if (!evp_pkey_copy_downgraded(&downgraded_from, from))
goto end;
from = downgraded_from;
}
/*
* Make sure |to| is typed. Content is less important at this early
* stage.
*
* 1. If |to| is untyped, assign |from|'s key type to it.
* 2. If |to| contains a legacy key, compare its |type| to |from|'s.
* (|from| was already downgraded above)
*
* If |to| is a provided key, there's nothing more to do here, functions
* like evp_keymgmt_util_copy() and evp_pkey_export_to_provider() called
* further down help us find out if they are the same or not.
*/
if (evp_pkey_is_blank(to)) {
if (evp_pkey_is_legacy(from)) {
if (EVP_PKEY_set_type(to, from->type) == 0)
goto end;
} else {
if (EVP_PKEY_set_type_by_keymgmt(to, from->keymgmt) == 0)
goto end;
}
} else if (evp_pkey_is_legacy(to)) {
if (to->type != from->type) {
ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
goto end;
}
}
if (EVP_PKEY_missing_parameters(from)) {
ERR_raise(ERR_LIB_EVP, EVP_R_MISSING_PARAMETERS);
goto end;
}
if (!EVP_PKEY_missing_parameters(to)) {
if (EVP_PKEY_parameters_eq(to, from) == 1)
ok = 1;
else
ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_PARAMETERS);
goto end;
}
/* For purely provided keys, we just call the keymgmt utility */
if (to->keymgmt != NULL && from->keymgmt != NULL) {
ok = evp_keymgmt_util_copy(to, (EVP_PKEY *)from, SELECT_PARAMETERS);
goto end;
}
/*
* If |to| is provided, we know that |from| is legacy at this point.
* Try exporting |from| to |to|'s keymgmt, then use evp_keymgmt_dup()
* to copy the appropriate data to |to|'s keydata.
* We cannot override existing data so do it only if there is no keydata
* in |to| yet.
*/
if (to->keymgmt != NULL && to->keydata == NULL) {
EVP_KEYMGMT *to_keymgmt = to->keymgmt;
void *from_keydata =
evp_pkey_export_to_provider((EVP_PKEY *)from, NULL, &to_keymgmt,
NULL);
/*
* If we get a NULL, it could be an internal error, or it could be
* that there's a key mismatch. We're pretending the latter...
*/
if (from_keydata == NULL)
ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
else
ok = (to->keydata = evp_keymgmt_dup(to->keymgmt,
from_keydata,
SELECT_PARAMETERS)) != NULL;
goto end;
}
/* Both keys are legacy */
if (from->ameth != NULL && from->ameth->param_copy != NULL)
ok = from->ameth->param_copy(to, from);
end:
EVP_PKEY_free(downgraded_from);
return ok;
}
int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey)
{
if (pkey != NULL) {
if (pkey->keymgmt != NULL)
return !evp_keymgmt_util_has((EVP_PKEY *)pkey, SELECT_PARAMETERS);
else if (pkey->ameth != NULL && pkey->ameth->param_missing != NULL)
return pkey->ameth->param_missing(pkey);
}
return 0;
}
/*
* This function is called for any mixture of keys except pure legacy pair.
* When legacy keys are gone, we replace a call to this functions with
* a call to evp_keymgmt_util_match().
*/
static int evp_pkey_cmp_any(const EVP_PKEY *a, const EVP_PKEY *b,
int selection)
{
EVP_KEYMGMT *keymgmt1 = NULL, *keymgmt2 = NULL;
void *keydata1 = NULL, *keydata2 = NULL, *tmp_keydata = NULL;
/* If none of them are provided, this function shouldn't have been called */
if (!ossl_assert(evp_pkey_is_provided(a) || evp_pkey_is_provided(b)))
return -2;
/* For purely provided keys, we just call the keymgmt utility */
if (evp_pkey_is_provided(a) && evp_pkey_is_provided(b))
return evp_keymgmt_util_match((EVP_PKEY *)a, (EVP_PKEY *)b, selection);
/*
* At this point, one of them is provided, the other not. This allows
* us to compare types using legacy NIDs.
*/
if (evp_pkey_is_legacy(a)
&& !EVP_KEYMGMT_is_a(b->keymgmt, OBJ_nid2sn(a->type)))
return -1; /* not the same key type */
if (evp_pkey_is_legacy(b)
&& !EVP_KEYMGMT_is_a(a->keymgmt, OBJ_nid2sn(b->type)))
return -1; /* not the same key type */
/*
* We've determined that they both are the same keytype, so the next
* step is to do a bit of cross export to ensure we have keydata for
* both keys in the same keymgmt.
*/
keymgmt1 = a->keymgmt;
keydata1 = a->keydata;
keymgmt2 = b->keymgmt;
keydata2 = b->keydata;
if (keymgmt2 != NULL && keymgmt2->match != NULL) {
tmp_keydata =
evp_pkey_export_to_provider((EVP_PKEY *)a, NULL, &keymgmt2, NULL);
if (tmp_keydata != NULL) {
keymgmt1 = keymgmt2;
keydata1 = tmp_keydata;
}
}
if (tmp_keydata == NULL && keymgmt1 != NULL && keymgmt1->match != NULL) {
tmp_keydata =
evp_pkey_export_to_provider((EVP_PKEY *)b, NULL, &keymgmt1, NULL);
if (tmp_keydata != NULL) {
keymgmt2 = keymgmt1;
keydata2 = tmp_keydata;
}
}
/* If we still don't have matching keymgmt implementations, we give up */
if (keymgmt1 != keymgmt2)
return -2;
/* If the keymgmt implementations are NULL, the export failed */
if (keymgmt1 == NULL)
return -2;
return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection);
}
# ifndef OPENSSL_NO_DEPRECATED_3_0
int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
{
return EVP_PKEY_parameters_eq(a, b);
}
#endif
int EVP_PKEY_parameters_eq(const EVP_PKEY *a, const EVP_PKEY *b)
{
/*
* This will just call evp_keymgmt_util_match when legacy support
* is gone.
*/
if (a->keymgmt != NULL || b->keymgmt != NULL)
return evp_pkey_cmp_any(a, b, SELECT_PARAMETERS);
/* All legacy keys */
if (a->type != b->type)
return -1;
if (a->ameth != NULL && a->ameth->param_cmp != NULL)
return a->ameth->param_cmp(a, b);
return -2;
}
# ifndef OPENSSL_NO_DEPRECATED_3_0
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
{
return EVP_PKEY_eq(a, b);
}
#endif
int EVP_PKEY_eq(const EVP_PKEY *a, const EVP_PKEY *b)
{
/*
* This will just call evp_keymgmt_util_match when legacy support
* is gone.
*/
/* Trivial shortcuts */
if (a == b)
return 1;
if (a == NULL || b == NULL)
return 0;
if (a->keymgmt != NULL || b->keymgmt != NULL) {
int selection = SELECT_PARAMETERS;
if (evp_keymgmt_util_has((EVP_PKEY *)a, OSSL_KEYMGMT_SELECT_PUBLIC_KEY)
&& evp_keymgmt_util_has((EVP_PKEY *)b, OSSL_KEYMGMT_SELECT_PUBLIC_KEY))
selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
else
selection |= OSSL_KEYMGMT_SELECT_KEYPAIR;
return evp_pkey_cmp_any(a, b, selection);
}
/* All legacy keys */
if (a->type != b->type)
return -1;
if (a->ameth != NULL) {
int ret;
/* Compare parameters if the algorithm has them */
if (a->ameth->param_cmp != NULL) {
ret = a->ameth->param_cmp(a, b);
if (ret <= 0)
return ret;
}
if (a->ameth->pub_cmp != NULL)
return a->ameth->pub_cmp(a, b);
}
return -2;
}
static EVP_PKEY *new_raw_key_int(OSSL_LIB_CTX *libctx,
const char *strtype,
const char *propq,
int nidtype,
ENGINE *e,
const unsigned char *key,
size_t len,
int key_is_priv)
{
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
const EVP_PKEY_ASN1_METHOD *ameth = NULL;
int result = 0;
# ifndef OPENSSL_NO_ENGINE
/* Check if there is an Engine for this type */
if (e == NULL) {
ENGINE *tmpe = NULL;
if (strtype != NULL)
ameth = EVP_PKEY_asn1_find_str(&tmpe, strtype, -1);
else if (nidtype != EVP_PKEY_NONE)
ameth = EVP_PKEY_asn1_find(&tmpe, nidtype);
/* If tmpe is NULL then no engine is claiming to support this type */
if (tmpe == NULL)
ameth = NULL;
ENGINE_finish(tmpe);
}
# endif
if (e == NULL && ameth == NULL) {
/*
* No engine is claiming to support this type, so lets see if we have
* a provider.
*/
ctx = EVP_PKEY_CTX_new_from_name(libctx,
strtype != NULL ? strtype
: OBJ_nid2sn(nidtype),
propq);
if (ctx == NULL)
goto err;
/* May fail if no provider available */
ERR_set_mark();
if (EVP_PKEY_fromdata_init(ctx) == 1) {
OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
ERR_clear_last_mark();
params[0] = OSSL_PARAM_construct_octet_string(
key_is_priv ? OSSL_PKEY_PARAM_PRIV_KEY
: OSSL_PKEY_PARAM_PUB_KEY,
(void *)key, len);
if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) != 1) {
ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
goto err;
}
EVP_PKEY_CTX_free(ctx);
return pkey;
}
ERR_pop_to_mark();
/* else not supported so fallback to legacy */
}
/* Legacy code path */
pkey = EVP_PKEY_new();
if (pkey == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!pkey_set_type(pkey, e, nidtype, strtype, -1, NULL)) {
/* EVPerr already called */
goto err;
}
if (!ossl_assert(pkey->ameth != NULL))
goto err;
if (key_is_priv) {
if (pkey->ameth->set_priv_key == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
goto err;
}
if (!pkey->ameth->set_priv_key(pkey, key, len)) {
ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
goto err;
}
} else {
if (pkey->ameth->set_pub_key == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
goto err;
}
if (!pkey->ameth->set_pub_key(pkey, key, len)) {
ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
goto err;
}
}
result = 1;
err:
if (!result) {
EVP_PKEY_free(pkey);
pkey = NULL;
}
EVP_PKEY_CTX_free(ctx);
return pkey;
}
EVP_PKEY *EVP_PKEY_new_raw_private_key_ex(OSSL_LIB_CTX *libctx,
const char *keytype,
const char *propq,
const unsigned char *priv, size_t len)
{
return new_raw_key_int(libctx, keytype, propq, EVP_PKEY_NONE, NULL, priv,
len, 1);
}
EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
const unsigned char *priv,
size_t len)
{
return new_raw_key_int(NULL, NULL, NULL, type, e, priv, len, 1);
}
EVP_PKEY *EVP_PKEY_new_raw_public_key_ex(OSSL_LIB_CTX *libctx,
const char *keytype, const char *propq,
const unsigned char *pub, size_t len)
{
return new_raw_key_int(libctx, keytype, propq, EVP_PKEY_NONE, NULL, pub,
len, 0);
}
EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
const unsigned char *pub,
size_t len)
{
return new_raw_key_int(NULL, NULL, NULL, type, e, pub, len, 0);
}
struct raw_key_details_st
{
unsigned char **key;
size_t *len;
int selection;
};
static OSSL_CALLBACK get_raw_key_details;
static int get_raw_key_details(const OSSL_PARAM params[], void *arg)
{
const OSSL_PARAM *p = NULL;
struct raw_key_details_st *raw_key = arg;
if (raw_key->selection == OSSL_KEYMGMT_SELECT_PRIVATE_KEY) {
if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY))
!= NULL)
return OSSL_PARAM_get_octet_string(p, (void **)raw_key->key,
raw_key->key == NULL ? 0 : *raw_key->len,
raw_key->len);
} else if (raw_key->selection == OSSL_KEYMGMT_SELECT_PUBLIC_KEY) {
if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY))
!= NULL)
return OSSL_PARAM_get_octet_string(p, (void **)raw_key->key,
raw_key->key == NULL ? 0 : *raw_key->len,
raw_key->len);
}
return 0;
}
int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
size_t *len)
{
if (pkey->keymgmt != NULL) {
struct raw_key_details_st raw_key;
raw_key.key = priv == NULL ? NULL : &priv;
raw_key.len = len;
raw_key.selection = OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
return evp_keymgmt_util_export(pkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
get_raw_key_details, &raw_key);
}
if (pkey->ameth == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (pkey->ameth->get_priv_key == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (!pkey->ameth->get_priv_key(pkey, priv, len)) {
ERR_raise(ERR_LIB_EVP, EVP_R_GET_RAW_KEY_FAILED);
return 0;
}
return 1;
}
int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
size_t *len)
{
if (pkey->keymgmt != NULL) {
struct raw_key_details_st raw_key;
raw_key.key = pub == NULL ? NULL : &pub;
raw_key.len = len;
raw_key.selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
return evp_keymgmt_util_export(pkey, OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
get_raw_key_details, &raw_key);
}
if (pkey->ameth == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (pkey->ameth->get_pub_key == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (!pkey->ameth->get_pub_key(pkey, pub, len)) {
ERR_raise(ERR_LIB_EVP, EVP_R_GET_RAW_KEY_FAILED);
return 0;
}
return 1;
}
static EVP_PKEY *new_cmac_key_int(const unsigned char *priv, size_t len,
const char *cipher_name,
const EVP_CIPHER *cipher,
OSSL_LIB_CTX *libctx,
const char *propq, ENGINE *e)
{
# ifndef OPENSSL_NO_CMAC
# ifndef OPENSSL_NO_ENGINE
const char *engine_id = e != NULL ? ENGINE_get_id(e) : NULL;
# endif
OSSL_PARAM params[5], *p = params;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx;
if (cipher != NULL)
cipher_name = EVP_CIPHER_get0_name(cipher);
if (cipher_name == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
return NULL;
}
ctx = EVP_PKEY_CTX_new_from_name(libctx, "CMAC", propq);
if (ctx == NULL)
goto err;
if (EVP_PKEY_fromdata_init(ctx) <= 0) {
ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
goto err;
}
*p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
(void *)priv, len);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_CIPHER,
(char *)cipher_name, 0);
if (propq != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_PROPERTIES,
(char *)propq, 0);
# ifndef OPENSSL_NO_ENGINE
if (engine_id != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_ENGINE,
(char *)engine_id, 0);
# endif
*p = OSSL_PARAM_construct_end();
if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
goto err;
}
err:
EVP_PKEY_CTX_free(ctx);
return pkey;
# else
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return NULL;
# endif
}
EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
size_t len, const EVP_CIPHER *cipher)
{
return new_cmac_key_int(priv, len, NULL, cipher, NULL, NULL, e);
}
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
{
return pkey_set_type(pkey, NULL, type, NULL, -1, NULL);
}
int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
{
return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len, NULL);
}
# ifndef OPENSSL_NO_ENGINE
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e)
{
if (e != NULL) {
if (!ENGINE_init(e)) {
ERR_raise(ERR_LIB_EVP, ERR_R_ENGINE_LIB);
return 0;
}
if (ENGINE_get_pkey_meth(e, pkey->type) == NULL) {
ENGINE_finish(e);
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
}
ENGINE_finish(pkey->pmeth_engine);
pkey->pmeth_engine = e;
return 1;
}
ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey)
{
return pkey->engine;
}
# endif
# ifndef OPENSSL_NO_DEPRECATED_3_0
static void detect_foreign_key(EVP_PKEY *pkey)
{
switch (pkey->type) {
case EVP_PKEY_RSA:
pkey->foreign = pkey->pkey.rsa != NULL
&& ossl_rsa_is_foreign(pkey->pkey.rsa);
break;
# ifndef OPENSSL_NO_EC
case EVP_PKEY_SM2:
case EVP_PKEY_EC:
pkey->foreign = pkey->pkey.ec != NULL
&& ossl_ec_key_is_foreign(pkey->pkey.ec);
break;
# endif
# ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
pkey->foreign = pkey->pkey.dsa != NULL
&& ossl_dsa_is_foreign(pkey->pkey.dsa);
break;
#endif
# ifndef OPENSSL_NO_DH
case EVP_PKEY_DH:
pkey->foreign = pkey->pkey.dh != NULL
&& ossl_dh_is_foreign(pkey->pkey.dh);
break;
#endif
default:
pkey->foreign = 0;
break;
}
}
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
{
# ifndef OPENSSL_NO_EC
int pktype;
pktype = EVP_PKEY_type(type);
if ((key != NULL) && (pktype == EVP_PKEY_EC || pktype == EVP_PKEY_SM2)) {
const EC_GROUP *group = EC_KEY_get0_group(key);
if (group != NULL) {
int curve = EC_GROUP_get_curve_name(group);
/*
* Regardless of what is requested the SM2 curve must be SM2 type,
* and non SM2 curves are EC type.
*/
if (curve == NID_sm2 && pktype == EVP_PKEY_EC)
type = EVP_PKEY_SM2;
else if(curve != NID_sm2 && pktype == EVP_PKEY_SM2)
type = EVP_PKEY_EC;
}
}
# endif
if (pkey == NULL || !EVP_PKEY_set_type(pkey, type))
return 0;
pkey->pkey.ptr = key;
detect_foreign_key(pkey);
return (key != NULL);
}
# endif
void *EVP_PKEY_get0(const EVP_PKEY *pkey)
{
if (pkey == NULL)
return NULL;
if (!evp_pkey_is_provided(pkey))
return pkey->pkey.ptr;
return NULL;
}
const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len)
{
const ASN1_OCTET_STRING *os = NULL;
if (pkey->type != EVP_PKEY_HMAC) {
ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_AN_HMAC_KEY);
return NULL;
}
os = evp_pkey_get_legacy((EVP_PKEY *)pkey);
if (os != NULL) {
*len = os->length;
return os->data;
}
return NULL;
}
# ifndef OPENSSL_NO_POLY1305
const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len)
{
const ASN1_OCTET_STRING *os = NULL;
if (pkey->type != EVP_PKEY_POLY1305) {
ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_POLY1305_KEY);
return NULL;
}
os = evp_pkey_get_legacy((EVP_PKEY *)pkey);
if (os != NULL) {
*len = os->length;
return os->data;
}
return NULL;
}
# endif
# ifndef OPENSSL_NO_SIPHASH
const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len)
{
const ASN1_OCTET_STRING *os = NULL;
if (pkey->type != EVP_PKEY_SIPHASH) {
ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_SIPHASH_KEY);
return NULL;
}
os = evp_pkey_get_legacy((EVP_PKEY *)pkey);
if (os != NULL) {
*len = os->length;
return os->data;
}
return NULL;
}
# endif
# ifndef OPENSSL_NO_DSA
static DSA *evp_pkey_get0_DSA_int(const EVP_PKEY *pkey)
{
if (pkey->type != EVP_PKEY_DSA) {
ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_DSA_KEY);
return NULL;
}
return evp_pkey_get_legacy((EVP_PKEY *)pkey);
}
const DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey)
{
return evp_pkey_get0_DSA_int(pkey);
}
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
{
int ret = EVP_PKEY_assign_DSA(pkey, key);
if (ret)
DSA_up_ref(key);
return ret;
}
DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey)
{
DSA *ret = evp_pkey_get0_DSA_int(pkey);
if (ret != NULL)
DSA_up_ref(ret);
return ret;
}
# endif /* OPENSSL_NO_DSA */
# ifndef OPENSSL_NO_EC
static const ECX_KEY *evp_pkey_get0_ECX_KEY(const EVP_PKEY *pkey, int type)
{
if (EVP_PKEY_get_base_id(pkey) != type) {
ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_ECX_KEY);
return NULL;
}
return evp_pkey_get_legacy((EVP_PKEY *)pkey);
}
static ECX_KEY *evp_pkey_get1_ECX_KEY(EVP_PKEY *pkey, int type)
{
ECX_KEY *ret = (ECX_KEY *)evp_pkey_get0_ECX_KEY(pkey, type);
if (ret != NULL && !ossl_ecx_key_up_ref(ret))
ret = NULL;
return ret;
}
# define IMPLEMENT_ECX_VARIANT(NAME) \
ECX_KEY *ossl_evp_pkey_get1_##NAME(EVP_PKEY *pkey) \
{ \
return evp_pkey_get1_ECX_KEY(pkey, EVP_PKEY_##NAME); \
}
IMPLEMENT_ECX_VARIANT(X25519)
IMPLEMENT_ECX_VARIANT(X448)
IMPLEMENT_ECX_VARIANT(ED25519)
IMPLEMENT_ECX_VARIANT(ED448)
# endif
# if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0)
int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *dhkey)
{
int ret, type;
/*
* ossl_dh_is_named_safe_prime_group() returns 1 for named safe prime groups
* related to ffdhe and modp (which cache q = (p - 1) / 2),
* and returns 0 for all other dh parameter generation types including
* RFC5114 named groups.
*
* The EVP_PKEY_DH type is used for dh parameter generation types:
* - named safe prime groups related to ffdhe and modp
* - safe prime generator
*
* The type EVP_PKEY_DHX is used for dh parameter generation types
* - fips186-4 and fips186-2
* - rfc5114 named groups.
*
* The EVP_PKEY_DH type is used to save PKCS#3 data than can be stored
* without a q value.
* The EVP_PKEY_DHX type is used to save X9.42 data that requires the
* q value to be stored.
*/
if (ossl_dh_is_named_safe_prime_group(dhkey))
type = EVP_PKEY_DH;
else
type = DH_get0_q(dhkey) == NULL ? EVP_PKEY_DH : EVP_PKEY_DHX;
ret = EVP_PKEY_assign(pkey, type, dhkey);
if (ret)
DH_up_ref(dhkey);
return ret;
}
DH *evp_pkey_get0_DH_int(const EVP_PKEY *pkey)
{
if (pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) {
ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_DH_KEY);
return NULL;
}
return evp_pkey_get_legacy((EVP_PKEY *)pkey);
}
const DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey)
{
return evp_pkey_get0_DH_int(pkey);
}
DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey)
{
DH *ret = evp_pkey_get0_DH_int(pkey);
if (ret != NULL)
DH_up_ref(ret);
return ret;
}
# endif
int EVP_PKEY_type(int type)
{
int ret;
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE *e;
ameth = EVP_PKEY_asn1_find(&e, type);
if (ameth)
ret = ameth->pkey_id;
else
ret = NID_undef;
# ifndef OPENSSL_NO_ENGINE
ENGINE_finish(e);
# endif
return ret;
}
int EVP_PKEY_get_id(const EVP_PKEY *pkey)
{
return pkey->type;
}
int EVP_PKEY_get_base_id(const EVP_PKEY *pkey)
{
return EVP_PKEY_type(pkey->type);
}
/*
* These hard coded cases are pure hackery to get around the fact
* that names in crypto/objects/objects.txt are a mess. There is
* no "EC", and "RSA" leads to the NID for 2.5.8.1.1, an OID that's
* fallen out in favor of { pkcs-1 1 }, i.e. 1.2.840.113549.1.1.1,
* the NID of which is used for EVP_PKEY_RSA. Strangely enough,
* "DSA" is accurate... but still, better be safe and hard-code
* names that we know.
* On a similar topic, EVP_PKEY_type(EVP_PKEY_SM2) will result in
* EVP_PKEY_EC, because of aliasing.
* This should be cleaned away along with all other #legacy support.
*/
static const OSSL_ITEM standard_name2type[] = {
{ EVP_PKEY_RSA, "RSA" },
{ EVP_PKEY_RSA_PSS, "RSA-PSS" },
{ EVP_PKEY_EC, "EC" },
{ EVP_PKEY_ED25519, "ED25519" },
{ EVP_PKEY_ED448, "ED448" },
{ EVP_PKEY_X25519, "X25519" },
{ EVP_PKEY_X448, "X448" },
{ EVP_PKEY_SM2, "SM2" },
{ EVP_PKEY_DH, "DH" },
{ EVP_PKEY_DHX, "X9.42 DH" },
{ EVP_PKEY_DHX, "DHX" },
{ EVP_PKEY_DSA, "DSA" },
};
int evp_pkey_name2type(const char *name)
{
int type;
size_t i;
for (i = 0; i < OSSL_NELEM(standard_name2type); i++) {
if (OPENSSL_strcasecmp(name, standard_name2type[i].ptr) == 0)
return (int)standard_name2type[i].id;
}
if ((type = EVP_PKEY_type(OBJ_sn2nid(name))) != NID_undef)
return type;
return EVP_PKEY_type(OBJ_ln2nid(name));
}
const char *evp_pkey_type2name(int type)
{
size_t i;
for (i = 0; i < OSSL_NELEM(standard_name2type); i++) {
if (type == (int)standard_name2type[i].id)
return standard_name2type[i].ptr;
}
return OBJ_nid2sn(type);
}
int EVP_PKEY_is_a(const EVP_PKEY *pkey, const char *name)
{
if (pkey == NULL)
return 0;
if (pkey->keymgmt == NULL)
return pkey->type == evp_pkey_name2type(name);
return EVP_KEYMGMT_is_a(pkey->keymgmt, name);
}
int EVP_PKEY_type_names_do_all(const EVP_PKEY *pkey,
void (*fn)(const char *name, void *data),
void *data)
{
if (!evp_pkey_is_typed(pkey))
return 0;
if (!evp_pkey_is_provided(pkey)) {
const char *name = OBJ_nid2sn(EVP_PKEY_get_id(pkey));
fn(name, data);
return 1;
}
return EVP_KEYMGMT_names_do_all(pkey->keymgmt, fn, data);
}
int EVP_PKEY_can_sign(const EVP_PKEY *pkey)
{
if (pkey->keymgmt == NULL) {
switch (EVP_PKEY_get_base_id(pkey)) {
case EVP_PKEY_RSA:
return 1;
# ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
return 1;
# endif
# ifndef OPENSSL_NO_EC
case EVP_PKEY_ED25519:
case EVP_PKEY_ED448:
return 1;
case EVP_PKEY_EC: /* Including SM2 */
return EC_KEY_can_sign(pkey->pkey.ec);
# endif
default:
break;
}
} else {
const OSSL_PROVIDER *prov = EVP_KEYMGMT_get0_provider(pkey->keymgmt);
OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
const char *supported_sig =
pkey->keymgmt->query_operation_name != NULL
? pkey->keymgmt->query_operation_name(OSSL_OP_SIGNATURE)
: EVP_KEYMGMT_get0_name(pkey->keymgmt);
EVP_SIGNATURE *signature = NULL;
signature = EVP_SIGNATURE_fetch(libctx, supported_sig, NULL);
if (signature != NULL) {
EVP_SIGNATURE_free(signature);
return 1;
}
}
return 0;
}
static int print_reset_indent(BIO **out, int pop_f_prefix, long saved_indent)
{
BIO_set_indent(*out, saved_indent);
if (pop_f_prefix) {
BIO *next = BIO_pop(*out);
BIO_free(*out);
*out = next;
}
return 1;
}
static int print_set_indent(BIO **out, int *pop_f_prefix, long *saved_indent,
long indent)
{
*pop_f_prefix = 0;
*saved_indent = 0;
if (indent > 0) {
long i = BIO_get_indent(*out);
*saved_indent = (i < 0 ? 0 : i);
if (BIO_set_indent(*out, indent) <= 0) {
BIO *prefbio = BIO_new(BIO_f_prefix());
if (prefbio == NULL)
return 0;
*out = BIO_push(prefbio, *out);
*pop_f_prefix = 1;
}
if (BIO_set_indent(*out, indent) <= 0) {
print_reset_indent(out, *pop_f_prefix, *saved_indent);
return 0;
}
}
return 1;
}
static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent,
const char *kstr)
{
return BIO_indent(out, indent, 128)
&& BIO_printf(out, "%s algorithm \"%s\" unsupported\n",
kstr, OBJ_nid2ln(pkey->type)) > 0;
}
static int print_pkey(const EVP_PKEY *pkey, BIO *out, int indent,
int selection /* For provided encoding */,
const char *propquery /* For provided encoding */,
int (*legacy_print)(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx),
ASN1_PCTX *legacy_pctx /* For legacy print */)
{
int pop_f_prefix;
long saved_indent;
OSSL_ENCODER_CTX *ctx = NULL;
int ret = -2; /* default to unsupported */
if (!print_set_indent(&out, &pop_f_prefix, &saved_indent, indent))
return 0;
ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "TEXT", NULL,
propquery);
if (OSSL_ENCODER_CTX_get_num_encoders(ctx) != 0)
ret = OSSL_ENCODER_to_bio(ctx, out);
OSSL_ENCODER_CTX_free(ctx);
if (ret != -2)
goto end;
/* legacy fallback */
if (legacy_print != NULL)
ret = legacy_print(out, pkey, 0, legacy_pctx);
else
ret = unsup_alg(out, pkey, 0, "Public Key");
end:
print_reset_indent(&out, pop_f_prefix, saved_indent);
return ret;
}
int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
return print_pkey(pkey, out, indent, EVP_PKEY_PUBLIC_KEY, NULL,
(pkey->ameth != NULL ? pkey->ameth->pub_print : NULL),
pctx);
}
int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
return print_pkey(pkey, out, indent, EVP_PKEY_KEYPAIR, NULL,
(pkey->ameth != NULL ? pkey->ameth->priv_print : NULL),
pctx);
}
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
return print_pkey(pkey, out, indent, EVP_PKEY_KEY_PARAMETERS, NULL,
(pkey->ameth != NULL ? pkey->ameth->param_print : NULL),
pctx);
}
# ifndef OPENSSL_NO_STDIO
int EVP_PKEY_print_public_fp(FILE *fp, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
int ret;
BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
if (b == NULL)
return 0;
ret = EVP_PKEY_print_public(b, pkey, indent, pctx);
BIO_free(b);
return ret;
}
int EVP_PKEY_print_private_fp(FILE *fp, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
int ret;
BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
if (b == NULL)
return 0;
ret = EVP_PKEY_print_private(b, pkey, indent, pctx);
BIO_free(b);
return ret;
}
int EVP_PKEY_print_params_fp(FILE *fp, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
int ret;
BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
if (b == NULL)
return 0;
ret = EVP_PKEY_print_params(b, pkey, indent, pctx);
BIO_free(b);
return ret;
}
# endif
static void mdname2nid(const char *mdname, void *data)
{
int *nid = (int *)data;
if (*nid != NID_undef)
return;
*nid = OBJ_sn2nid(mdname);
if (*nid == NID_undef)
*nid = OBJ_ln2nid(mdname);
}
static int legacy_asn1_ctrl_to_param(EVP_PKEY *pkey, int op,
int arg1, void *arg2)
{
if (pkey->keymgmt == NULL)
return 0;
switch (op) {
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
{
char mdname[80] = "";
int rv = EVP_PKEY_get_default_digest_name(pkey, mdname,
sizeof(mdname));
if (rv > 0) {
int mdnum;
OSSL_LIB_CTX *libctx = ossl_provider_libctx(pkey->keymgmt->prov);
/* Make sure the MD is in the namemap if available */
EVP_MD *md;
OSSL_NAMEMAP *namemap;
int nid = NID_undef;
(void)ERR_set_mark();
md = EVP_MD_fetch(libctx, mdname, NULL);
(void)ERR_pop_to_mark();
namemap = ossl_namemap_stored(libctx);
/*
* The only reason to fetch the MD was to make sure it is in the
* namemap. We can immediately free it.
*/
EVP_MD_free(md);
mdnum = ossl_namemap_name2num(namemap, mdname);
if (mdnum == 0)
return 0;
/*
* We have the namemap number - now we need to find the
* associated nid
*/
if (!ossl_namemap_doall_names(namemap, mdnum, mdname2nid, &nid))
return 0;
*(int *)arg2 = nid;
}
return rv;
}
default:
return -2;
}
}
static int evp_pkey_asn1_ctrl(EVP_PKEY *pkey, int op, int arg1, void *arg2)
{
if (pkey->ameth == NULL)
return legacy_asn1_ctrl_to_param(pkey, op, arg1, arg2);
if (pkey->ameth->pkey_ctrl == NULL)
return -2;
return pkey->ameth->pkey_ctrl(pkey, op, arg1, arg2);
}
int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid)
{
+ if (pkey == NULL)
+ return 0;
return evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID, 0, pnid);
}
int EVP_PKEY_get_default_digest_name(EVP_PKEY *pkey,
char *mdname, size_t mdname_sz)
{
if (pkey->ameth == NULL)
return evp_keymgmt_util_get_deflt_digest_name(pkey->keymgmt,
pkey->keydata,
mdname, mdname_sz);
{
int nid = NID_undef;
int rv = EVP_PKEY_get_default_digest_nid(pkey, &nid);
const char *name = rv > 0 ? OBJ_nid2sn(nid) : NULL;
if (rv > 0)
OPENSSL_strlcpy(mdname, name, mdname_sz);
return rv;
}
}
int EVP_PKEY_get_group_name(const EVP_PKEY *pkey, char *gname, size_t gname_sz,
size_t *gname_len)
{
return EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME,
gname, gname_sz, gname_len);
}
int EVP_PKEY_digestsign_supports_digest(EVP_PKEY *pkey, OSSL_LIB_CTX *libctx,
const char *name, const char *propq)
{
int rv;
EVP_MD_CTX *ctx = NULL;
if ((ctx = EVP_MD_CTX_new()) == NULL)
return -1;
ERR_set_mark();
rv = EVP_DigestSignInit_ex(ctx, NULL, name, libctx,
propq, pkey, NULL);
ERR_pop_to_mark();
EVP_MD_CTX_free(ctx);
return rv;
}
int EVP_PKEY_set1_encoded_public_key(EVP_PKEY *pkey, const unsigned char *pub,
size_t publen)
{
- if (pkey != NULL && evp_pkey_is_provided(pkey))
+ if (pkey == NULL)
+ return 0;
+ if (evp_pkey_is_provided(pkey))
return
EVP_PKEY_set_octet_string_param(pkey,
OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
(unsigned char *)pub, publen);
if (publen > INT_MAX)
return 0;
/* Historically this function was EVP_PKEY_set1_tls_encodedpoint */
if (evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_SET1_TLS_ENCPT, publen,
(void *)pub) <= 0)
return 0;
return 1;
}
size_t EVP_PKEY_get1_encoded_public_key(EVP_PKEY *pkey, unsigned char **ppub)
{
int rv;
- if (pkey != NULL && evp_pkey_is_provided(pkey)) {
+ if (pkey == NULL)
+ return 0;
+ if (evp_pkey_is_provided(pkey)) {
size_t return_size = OSSL_PARAM_UNMODIFIED;
unsigned char *buf;
/*
* We know that this is going to fail, but it will give us a size
* to allocate.
*/
EVP_PKEY_get_octet_string_param(pkey,
OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
NULL, 0, &return_size);
if (return_size == OSSL_PARAM_UNMODIFIED)
return 0;
*ppub = NULL;
buf = OPENSSL_malloc(return_size);
if (buf == NULL)
return 0;
if (!EVP_PKEY_get_octet_string_param(pkey,
OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
buf, return_size, NULL)) {
OPENSSL_free(buf);
return 0;
}
*ppub = buf;
return return_size;
}
rv = evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_GET1_TLS_ENCPT, 0, ppub);
if (rv <= 0)
return 0;
return rv;
}
#endif /* FIPS_MODULE */
/*- All methods below can also be used in FIPS_MODULE */
EVP_PKEY *EVP_PKEY_new(void)
{
EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->type = EVP_PKEY_NONE;
ret->save_type = EVP_PKEY_NONE;
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
EVPerr(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
goto err;
}
#ifndef FIPS_MODULE
ret->save_parameters = 1;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, ret, &ret->ex_data)) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
goto err;
}
#endif
return ret;
err:
CRYPTO_THREAD_lock_free(ret->lock);
OPENSSL_free(ret);
return NULL;
}
/*
* Setup a public key management method.
*
* For legacy keys, either |type| or |str| is expected to have the type
* information. In this case, the setup consists of finding an ASN1 method
* and potentially an ENGINE, and setting those fields in |pkey|.
*
* For provider side keys, |keymgmt| is expected to be non-NULL. In this
* case, the setup consists of setting the |keymgmt| field in |pkey|.
*
* If pkey is NULL just return 1 or 0 if the key management method exists.
*/
static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
int len, EVP_KEYMGMT *keymgmt)
{
#ifndef FIPS_MODULE
const EVP_PKEY_ASN1_METHOD *ameth = NULL;
ENGINE **eptr = (e == NULL) ? &e : NULL;
#endif
/*
* The setups can't set both legacy and provider side methods.
* It is forbidden
*/
if (!ossl_assert(type == EVP_PKEY_NONE || keymgmt == NULL)
|| !ossl_assert(e == NULL || keymgmt == NULL)) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return 0;
}
if (pkey != NULL) {
int free_it = 0;
#ifndef FIPS_MODULE
free_it = free_it || pkey->pkey.ptr != NULL;
#endif
free_it = free_it || pkey->keydata != NULL;
if (free_it)
evp_pkey_free_it(pkey);
#ifndef FIPS_MODULE
/*
* If key type matches and a method exists then this lookup has
* succeeded once so just indicate success.
*/
if (pkey->type != EVP_PKEY_NONE
&& type == pkey->save_type
&& pkey->ameth != NULL)
return 1;
# ifndef OPENSSL_NO_ENGINE
/* If we have ENGINEs release them */
ENGINE_finish(pkey->engine);
pkey->engine = NULL;
ENGINE_finish(pkey->pmeth_engine);
pkey->pmeth_engine = NULL;
# endif
#endif
}
#ifndef FIPS_MODULE
if (str != NULL)
ameth = EVP_PKEY_asn1_find_str(eptr, str, len);
else if (type != EVP_PKEY_NONE)
ameth = EVP_PKEY_asn1_find(eptr, type);
# ifndef OPENSSL_NO_ENGINE
if (pkey == NULL && eptr != NULL)
ENGINE_finish(e);
# endif
#endif
{
int check = 1;
#ifndef FIPS_MODULE
check = check && ameth == NULL;
#endif
check = check && keymgmt == NULL;
if (check) {
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
}
if (pkey != NULL) {
if (keymgmt != NULL && !EVP_KEYMGMT_up_ref(keymgmt)) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return 0;
}
pkey->keymgmt = keymgmt;
pkey->save_type = type;
pkey->type = type;
#ifndef FIPS_MODULE
/*
* If the internal "origin" key is provider side, don't save |ameth|.
* The main reason is that |ameth| is one factor to detect that the
* internal "origin" key is a legacy one.
*/
if (keymgmt == NULL)
pkey->ameth = ameth;
/*
* The EVP_PKEY_ASN1_METHOD |pkey_id| retains its legacy key purpose
* for any key type that has a legacy implementation, regardless of
* if the internal key is a legacy or a provider side one. When
* there is no legacy implementation for the key, the type becomes
* EVP_PKEY_KEYMGMT, which indicates that one should be cautious
* with functions that expect legacy internal keys.
*/
if (ameth != NULL) {
if (type == EVP_PKEY_NONE)
pkey->type = ameth->pkey_id;
} else {
pkey->type = EVP_PKEY_KEYMGMT;
}
# ifndef OPENSSL_NO_ENGINE
if (eptr == NULL && e != NULL && !ENGINE_init(e)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
return 0;
}
# endif
pkey->engine = e;
#endif
}
return 1;
}
#ifndef FIPS_MODULE
static void find_ameth(const char *name, void *data)
{
const char **str = data;
/*
* The error messages from pkey_set_type() are uninteresting here,
* and misleading.
*/
ERR_set_mark();
if (pkey_set_type(NULL, NULL, EVP_PKEY_NONE, name, strlen(name),
NULL)) {
if (str[0] == NULL)
str[0] = name;
else if (str[1] == NULL)
str[1] = name;
}
ERR_pop_to_mark();
}
#endif
int EVP_PKEY_set_type_by_keymgmt(EVP_PKEY *pkey, EVP_KEYMGMT *keymgmt)
{
#ifndef FIPS_MODULE
# define EVP_PKEY_TYPE_STR str[0]
# define EVP_PKEY_TYPE_STRLEN (str[0] == NULL ? -1 : (int)strlen(str[0]))
/*
* Find at most two strings that have an associated EVP_PKEY_ASN1_METHOD
* Ideally, only one should be found. If two (or more) are found, the
* match is ambiguous. This should never happen, but...
*/
const char *str[2] = { NULL, NULL };
if (!EVP_KEYMGMT_names_do_all(keymgmt, find_ameth, &str)
|| str[1] != NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return 0;
}
#else
# define EVP_PKEY_TYPE_STR NULL
# define EVP_PKEY_TYPE_STRLEN -1
#endif
return pkey_set_type(pkey, NULL, EVP_PKEY_NONE,
EVP_PKEY_TYPE_STR, EVP_PKEY_TYPE_STRLEN,
keymgmt);
#undef EVP_PKEY_TYPE_STR
#undef EVP_PKEY_TYPE_STRLEN
}
int EVP_PKEY_up_ref(EVP_PKEY *pkey)
{
int i;
if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0)
return 0;
REF_PRINT_COUNT("EVP_PKEY", pkey);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}
#ifndef FIPS_MODULE
EVP_PKEY *EVP_PKEY_dup(EVP_PKEY *pkey)
{
EVP_PKEY *dup_pk;
if (pkey == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if ((dup_pk = EVP_PKEY_new()) == NULL)
return NULL;
if (evp_pkey_is_blank(pkey))
goto done;
if (evp_pkey_is_provided(pkey)) {
if (!evp_keymgmt_util_copy(dup_pk, pkey,
OSSL_KEYMGMT_SELECT_ALL))
goto err;
goto done;
}
if (evp_pkey_is_legacy(pkey)) {
const EVP_PKEY_ASN1_METHOD *ameth = pkey->ameth;
if (ameth == NULL || ameth->copy == NULL) {
if (pkey->pkey.ptr == NULL /* empty key, just set type */
&& EVP_PKEY_set_type(dup_pk, pkey->type) != 0)
goto done;
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
goto err;
}
if (!ameth->copy(dup_pk, pkey))
goto err;
goto done;
}
goto err;
done:
/* copy auxiliary data */
if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EVP_PKEY,
&dup_pk->ex_data, &pkey->ex_data))
goto err;
if (pkey->attributes != NULL) {
if ((dup_pk->attributes = ossl_x509at_dup(pkey->attributes)) == NULL)
goto err;
}
return dup_pk;
err:
EVP_PKEY_free(dup_pk);
return NULL;
}
void evp_pkey_free_legacy(EVP_PKEY *x)
{
const EVP_PKEY_ASN1_METHOD *ameth = x->ameth;
ENGINE *tmpe = NULL;
if (ameth == NULL && x->legacy_cache_pkey.ptr != NULL)
ameth = EVP_PKEY_asn1_find(&tmpe, x->type);
if (ameth != NULL) {
if (x->legacy_cache_pkey.ptr != NULL) {
/*
* We should never have both a legacy origin key, and a key in the
* legacy cache.
*/
assert(x->pkey.ptr == NULL);
/*
* For the purposes of freeing we make the legacy cache look like
* a legacy origin key.
*/
x->pkey = x->legacy_cache_pkey;
x->legacy_cache_pkey.ptr = NULL;
}
if (ameth->pkey_free != NULL)
ameth->pkey_free(x);
x->pkey.ptr = NULL;
}
# ifndef OPENSSL_NO_ENGINE
ENGINE_finish(tmpe);
ENGINE_finish(x->engine);
x->engine = NULL;
ENGINE_finish(x->pmeth_engine);
x->pmeth_engine = NULL;
# endif
}
#endif /* FIPS_MODULE */
static void evp_pkey_free_it(EVP_PKEY *x)
{
/* internal function; x is never NULL */
evp_keymgmt_util_clear_operation_cache(x, 1);
#ifndef FIPS_MODULE
evp_pkey_free_legacy(x);
#endif
if (x->keymgmt != NULL) {
evp_keymgmt_freedata(x->keymgmt, x->keydata);
EVP_KEYMGMT_free(x->keymgmt);
x->keymgmt = NULL;
x->keydata = NULL;
}
x->type = EVP_PKEY_NONE;
}
void EVP_PKEY_free(EVP_PKEY *x)
{
int i;
if (x == NULL)
return;
CRYPTO_DOWN_REF(&x->references, &i, x->lock);
REF_PRINT_COUNT("EVP_PKEY", x);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
evp_pkey_free_it(x);
#ifndef FIPS_MODULE
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, x, &x->ex_data);
#endif
CRYPTO_THREAD_lock_free(x->lock);
#ifndef FIPS_MODULE
sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
#endif
OPENSSL_free(x);
}
int EVP_PKEY_get_size(const EVP_PKEY *pkey)
{
int size = 0;
if (pkey != NULL) {
size = pkey->cache.size;
#ifndef FIPS_MODULE
if (pkey->ameth != NULL && pkey->ameth->pkey_size != NULL)
size = pkey->ameth->pkey_size(pkey);
#endif
}
return size < 0 ? 0 : size;
}
const char *EVP_PKEY_get0_description(const EVP_PKEY *pkey)
{
if (!evp_pkey_is_assigned(pkey))
return NULL;
if (evp_pkey_is_provided(pkey) && pkey->keymgmt->description != NULL)
return pkey->keymgmt->description;
#ifndef FIPS_MODULE
if (pkey->ameth != NULL)
return pkey->ameth->info;
#endif
return NULL;
}
void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx,
EVP_KEYMGMT **keymgmt,
const char *propquery)
{
EVP_KEYMGMT *allocated_keymgmt = NULL;
EVP_KEYMGMT *tmp_keymgmt = NULL;
int selection = OSSL_KEYMGMT_SELECT_ALL;
void *keydata = NULL;
int check;
if (pk == NULL)
return NULL;
/* No key data => nothing to export */
check = 1;
#ifndef FIPS_MODULE
check = check && pk->pkey.ptr == NULL;
#endif
check = check && pk->keydata == NULL;
if (check)
return NULL;
#ifndef FIPS_MODULE
if (pk->pkey.ptr != NULL) {
/*
* If the legacy key doesn't have an dirty counter or export function,
* give up
*/
if (pk->ameth->dirty_cnt == NULL || pk->ameth->export_to == NULL)
return NULL;
}
#endif
if (keymgmt != NULL) {
tmp_keymgmt = *keymgmt;
*keymgmt = NULL;
}
/*
* If no keymgmt was given or found, get a default keymgmt. We do so by
* letting EVP_PKEY_CTX_new_from_pkey() do it for us, then we steal it.
*/
if (tmp_keymgmt == NULL) {
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pk, propquery);
if (ctx == NULL)
goto end;
allocated_keymgmt = tmp_keymgmt = ctx->keymgmt;
ctx->keymgmt = NULL;
EVP_PKEY_CTX_free(ctx);
}
/* If there's still no keymgmt to be had, give up */
if (tmp_keymgmt == NULL)
goto end;
#ifndef FIPS_MODULE
if (pk->pkey.ptr != NULL) {
OP_CACHE_ELEM *op;
/*
* If the legacy "origin" hasn't changed since last time, we try
* to find our keymgmt in the operation cache. If it has changed,
* |i| remains zero, and we will clear the cache further down.
*/
if (pk->ameth->dirty_cnt(pk) == pk->dirty_cnt_copy) {
if (!CRYPTO_THREAD_read_lock(pk->lock))
goto end;
op = evp_keymgmt_util_find_operation_cache(pk, tmp_keymgmt,
selection);
/*
* If |tmp_keymgmt| is present in the operation cache, it means
* that export doesn't need to be redone. In that case, we take
* token copies of the cached pointers, to have token success
* values to return.
*/
if (op != NULL && op->keymgmt != NULL) {
keydata = op->keydata;
CRYPTO_THREAD_unlock(pk->lock);
goto end;
}
CRYPTO_THREAD_unlock(pk->lock);
}
/* Make sure that the keymgmt key type matches the legacy NID */
if (!EVP_KEYMGMT_is_a(tmp_keymgmt, OBJ_nid2sn(pk->type)))
goto end;
if ((keydata = evp_keymgmt_newdata(tmp_keymgmt)) == NULL)
goto end;
if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt->import,
libctx, propquery)) {
evp_keymgmt_freedata(tmp_keymgmt, keydata);
keydata = NULL;
goto end;
}
/*
* If the dirty counter changed since last time, then clear the
* operation cache. In that case, we know that |i| is zero. Just
* in case this is a re-export, we increment then decrement the
* keymgmt reference counter.
*/
if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) { /* refcnt++ */
evp_keymgmt_freedata(tmp_keymgmt, keydata);
keydata = NULL;
goto end;
}
if (!CRYPTO_THREAD_write_lock(pk->lock))
goto end;
if (pk->ameth->dirty_cnt(pk) != pk->dirty_cnt_copy
&& !evp_keymgmt_util_clear_operation_cache(pk, 0)) {
CRYPTO_THREAD_unlock(pk->lock);
evp_keymgmt_freedata(tmp_keymgmt, keydata);
keydata = NULL;
EVP_KEYMGMT_free(tmp_keymgmt);
goto end;
}
EVP_KEYMGMT_free(tmp_keymgmt); /* refcnt-- */
/* Check to make sure some other thread didn't get there first */
op = evp_keymgmt_util_find_operation_cache(pk, tmp_keymgmt, selection);
if (op != NULL && op->keymgmt != NULL) {
void *tmp_keydata = op->keydata;
CRYPTO_THREAD_unlock(pk->lock);
evp_keymgmt_freedata(tmp_keymgmt, keydata);
keydata = tmp_keydata;
goto end;
}
/* Add the new export to the operation cache */
if (!evp_keymgmt_util_cache_keydata(pk, tmp_keymgmt, keydata,
selection)) {
CRYPTO_THREAD_unlock(pk->lock);
evp_keymgmt_freedata(tmp_keymgmt, keydata);
keydata = NULL;
goto end;
}
/* Synchronize the dirty count */
pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk);
CRYPTO_THREAD_unlock(pk->lock);
goto end;
}
#endif /* FIPS_MODULE */
keydata = evp_keymgmt_util_export_to_provider(pk, tmp_keymgmt, selection);
end:
/*
* If nothing was exported, |tmp_keymgmt| might point at a freed
* EVP_KEYMGMT, so we clear it to be safe. It shouldn't be useful for
* the caller either way in that case.
*/
if (keydata == NULL)
tmp_keymgmt = NULL;
if (keymgmt != NULL && tmp_keymgmt != NULL) {
*keymgmt = tmp_keymgmt;
allocated_keymgmt = NULL;
}
EVP_KEYMGMT_free(allocated_keymgmt);
return keydata;
}
#ifndef FIPS_MODULE
int evp_pkey_copy_downgraded(EVP_PKEY **dest, const EVP_PKEY *src)
{
EVP_PKEY *allocpkey = NULL;
if (!ossl_assert(dest != NULL))
return 0;
if (evp_pkey_is_assigned(src) && evp_pkey_is_provided(src)) {
EVP_KEYMGMT *keymgmt = src->keymgmt;
void *keydata = src->keydata;
int type = src->type;
const char *keytype = NULL;
keytype = EVP_KEYMGMT_get0_name(keymgmt);
/*
* If the type is EVP_PKEY_NONE, then we have a problem somewhere
* else in our code. If it's not one of the well known EVP_PKEY_xxx
* values, it should at least be EVP_PKEY_KEYMGMT at this point.
* The check is kept as a safety measure.
*/
if (!ossl_assert(type != EVP_PKEY_NONE)) {
ERR_raise_data(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR,
"keymgmt key type = %s but legacy type = EVP_PKEY_NONE",
keytype);
return 0;
}
/* Prefer the legacy key type name for error reporting */
if (type != EVP_PKEY_KEYMGMT)
keytype = OBJ_nid2sn(type);
/* Make sure we have a clean slate to copy into */
if (*dest == NULL) {
allocpkey = *dest = EVP_PKEY_new();
if (*dest == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
evp_pkey_free_it(*dest);
}
if (EVP_PKEY_set_type(*dest, type)) {
/* If the key is typed but empty, we're done */
if (keydata == NULL)
return 1;
if ((*dest)->ameth->import_from == NULL) {
ERR_raise_data(ERR_LIB_EVP, EVP_R_NO_IMPORT_FUNCTION,
"key type = %s", keytype);
} else {
/*
* We perform the export in the same libctx as the keymgmt
* that we are using.
*/
OSSL_LIB_CTX *libctx =
ossl_provider_libctx(keymgmt->prov);
EVP_PKEY_CTX *pctx =
EVP_PKEY_CTX_new_from_pkey(libctx, *dest, NULL);
if (pctx == NULL)
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
if (pctx != NULL
&& evp_keymgmt_export(keymgmt, keydata,
OSSL_KEYMGMT_SELECT_ALL,
(*dest)->ameth->import_from,
pctx)) {
/* Synchronize the dirty count */
(*dest)->dirty_cnt_copy = (*dest)->ameth->dirty_cnt(*dest);
EVP_PKEY_CTX_free(pctx);
return 1;
}
EVP_PKEY_CTX_free(pctx);
}
ERR_raise_data(ERR_LIB_EVP, EVP_R_KEYMGMT_EXPORT_FAILURE,
"key type = %s", keytype);
}
}
if (allocpkey != NULL) {
EVP_PKEY_free(allocpkey);
*dest = NULL;
}
return 0;
}
void *evp_pkey_get_legacy(EVP_PKEY *pk)
{
EVP_PKEY *tmp_copy = NULL;
void *ret = NULL;
if (!ossl_assert(pk != NULL))
return NULL;
/*
* If this isn't an assigned provider side key, we just use any existing
* origin legacy key.
*/
if (!evp_pkey_is_assigned(pk))
return NULL;
if (!evp_pkey_is_provided(pk))
return pk->pkey.ptr;
if (!CRYPTO_THREAD_read_lock(pk->lock))
return NULL;
ret = pk->legacy_cache_pkey.ptr;
if (!CRYPTO_THREAD_unlock(pk->lock))
return NULL;
if (ret != NULL)
return ret;
if (!evp_pkey_copy_downgraded(&tmp_copy, pk))
goto err;
if (!CRYPTO_THREAD_write_lock(pk->lock))
goto err;
/* Check again in case some other thread has updated it in the meantime */
ret = pk->legacy_cache_pkey.ptr;
if (ret == NULL) {
/* Steal the legacy key reference from the temporary copy */
ret = pk->legacy_cache_pkey.ptr = tmp_copy->pkey.ptr;
tmp_copy->pkey.ptr = NULL;
}
if (!CRYPTO_THREAD_unlock(pk->lock)) {
ret = NULL;
goto err;
}
err:
EVP_PKEY_free(tmp_copy);
return ret;
}
#endif /* FIPS_MODULE */
int EVP_PKEY_get_bn_param(const EVP_PKEY *pkey, const char *key_name,
BIGNUM **bn)
{
int ret = 0;
OSSL_PARAM params[2];
unsigned char buffer[2048];
unsigned char *buf = NULL;
size_t buf_sz = 0;
if (key_name == NULL
|| bn == NULL)
return 0;
memset(buffer, 0, sizeof(buffer));
params[0] = OSSL_PARAM_construct_BN(key_name, buffer, sizeof(buffer));
params[1] = OSSL_PARAM_construct_end();
if (!EVP_PKEY_get_params(pkey, params)) {
if (!OSSL_PARAM_modified(params) || params[0].return_size == 0)
return 0;
buf_sz = params[0].return_size;
/*
* If it failed because the buffer was too small then allocate the
* required buffer size and retry.
*/
buf = OPENSSL_zalloc(buf_sz);
if (buf == NULL)
return 0;
params[0].data = buf;
params[0].data_size = buf_sz;
if (!EVP_PKEY_get_params(pkey, params))
goto err;
}
/* Fail if the param was not found */
if (!OSSL_PARAM_modified(params))
goto err;
ret = OSSL_PARAM_get_BN(params, bn);
err:
- OPENSSL_free(buf);
+ if (buf != NULL) {
+ if (OSSL_PARAM_modified(params))
+ OPENSSL_clear_free(buf, buf_sz);
+ else
+ OPENSSL_free(buf);
+ } else if (OSSL_PARAM_modified(params)) {
+ OPENSSL_cleanse(buffer, params[0].data_size);
+ }
return ret;
}
int EVP_PKEY_get_octet_string_param(const EVP_PKEY *pkey, const char *key_name,
unsigned char *buf, size_t max_buf_sz,
size_t *out_len)
{
OSSL_PARAM params[2];
int ret1 = 0, ret2 = 0;
if (key_name == NULL)
return 0;
params[0] = OSSL_PARAM_construct_octet_string(key_name, buf, max_buf_sz);
params[1] = OSSL_PARAM_construct_end();
if ((ret1 = EVP_PKEY_get_params(pkey, params)))
ret2 = OSSL_PARAM_modified(params);
if (ret2 && out_len != NULL)
*out_len = params[0].return_size;
return ret1 && ret2;
}
int EVP_PKEY_get_utf8_string_param(const EVP_PKEY *pkey, const char *key_name,
char *str, size_t max_buf_sz,
size_t *out_len)
{
OSSL_PARAM params[2];
int ret1 = 0, ret2 = 0;
if (key_name == NULL)
return 0;
params[0] = OSSL_PARAM_construct_utf8_string(key_name, str, max_buf_sz);
params[1] = OSSL_PARAM_construct_end();
if ((ret1 = EVP_PKEY_get_params(pkey, params)))
ret2 = OSSL_PARAM_modified(params);
if (ret2 && out_len != NULL)
*out_len = params[0].return_size;
if (ret2 && params[0].return_size == max_buf_sz)
/* There was no space for a NUL byte */
return 0;
/* Add a terminating NUL byte for good measure */
if (ret2 && str != NULL)
str[params[0].return_size] = '\0';
return ret1 && ret2;
}
int EVP_PKEY_get_int_param(const EVP_PKEY *pkey, const char *key_name,
int *out)
{
OSSL_PARAM params[2];
if (key_name == NULL)
return 0;
params[0] = OSSL_PARAM_construct_int(key_name, out);
params[1] = OSSL_PARAM_construct_end();
return EVP_PKEY_get_params(pkey, params)
&& OSSL_PARAM_modified(params);
}
int EVP_PKEY_get_size_t_param(const EVP_PKEY *pkey, const char *key_name,
size_t *out)
{
OSSL_PARAM params[2];
if (key_name == NULL)
return 0;
params[0] = OSSL_PARAM_construct_size_t(key_name, out);
params[1] = OSSL_PARAM_construct_end();
return EVP_PKEY_get_params(pkey, params)
&& OSSL_PARAM_modified(params);
}
int EVP_PKEY_set_int_param(EVP_PKEY *pkey, const char *key_name, int in)
{
OSSL_PARAM params[2];
if (key_name == NULL)
return 0;
params[0] = OSSL_PARAM_construct_int(key_name, &in);
params[1] = OSSL_PARAM_construct_end();
return EVP_PKEY_set_params(pkey, params);
}
int EVP_PKEY_set_size_t_param(EVP_PKEY *pkey, const char *key_name, size_t in)
{
OSSL_PARAM params[2];
if (key_name == NULL)
return 0;
params[0] = OSSL_PARAM_construct_size_t(key_name, &in);
params[1] = OSSL_PARAM_construct_end();
return EVP_PKEY_set_params(pkey, params);
}
int EVP_PKEY_set_bn_param(EVP_PKEY *pkey, const char *key_name,
const BIGNUM *bn)
{
OSSL_PARAM params[2];
unsigned char buffer[2048];
int bsize = 0;
if (key_name == NULL
|| bn == NULL
|| pkey == NULL
|| !evp_pkey_is_assigned(pkey))
return 0;
bsize = BN_num_bytes(bn);
if (!ossl_assert(bsize <= (int)sizeof(buffer)))
return 0;
if (BN_bn2nativepad(bn, buffer, bsize) < 0)
return 0;
params[0] = OSSL_PARAM_construct_BN(key_name, buffer, bsize);
params[1] = OSSL_PARAM_construct_end();
return EVP_PKEY_set_params(pkey, params);
}
int EVP_PKEY_set_utf8_string_param(EVP_PKEY *pkey, const char *key_name,
const char *str)
{
OSSL_PARAM params[2];
if (key_name == NULL)
return 0;
params[0] = OSSL_PARAM_construct_utf8_string(key_name, (char *)str, 0);
params[1] = OSSL_PARAM_construct_end();
return EVP_PKEY_set_params(pkey, params);
}
int EVP_PKEY_set_octet_string_param(EVP_PKEY *pkey, const char *key_name,
const unsigned char *buf, size_t bsize)
{
OSSL_PARAM params[2];
if (key_name == NULL)
return 0;
params[0] = OSSL_PARAM_construct_octet_string(key_name,
(unsigned char *)buf, bsize);
params[1] = OSSL_PARAM_construct_end();
return EVP_PKEY_set_params(pkey, params);
}
const OSSL_PARAM *EVP_PKEY_settable_params(const EVP_PKEY *pkey)
{
return (pkey != NULL && evp_pkey_is_provided(pkey))
? EVP_KEYMGMT_settable_params(pkey->keymgmt)
: NULL;
}
int EVP_PKEY_set_params(EVP_PKEY *pkey, OSSL_PARAM params[])
{
if (pkey != NULL) {
if (evp_pkey_is_provided(pkey)) {
pkey->dirty_cnt++;
return evp_keymgmt_set_params(pkey->keymgmt, pkey->keydata, params);
}
#ifndef FIPS_MODULE
/*
* We will hopefully never find the need to set individual data in
* EVP_PKEYs with a legacy internal key, but we can't be entirely
* sure. This bit of code can be enabled if we find the need. If
* not, it can safely be removed when #legacy support is removed.
*/
# if 0
else if (evp_pkey_is_legacy(pkey)) {
return evp_pkey_set_params_to_ctrl(pkey, params);
}
# endif
#endif
}
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY);
return 0;
}
const OSSL_PARAM *EVP_PKEY_gettable_params(const EVP_PKEY *pkey)
{
return (pkey != NULL && evp_pkey_is_provided(pkey))
? EVP_KEYMGMT_gettable_params(pkey->keymgmt)
: NULL;
}
int EVP_PKEY_get_params(const EVP_PKEY *pkey, OSSL_PARAM params[])
{
if (pkey != NULL) {
if (evp_pkey_is_provided(pkey))
return evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params) > 0;
#ifndef FIPS_MODULE
else if (evp_pkey_is_legacy(pkey))
return evp_pkey_get_params_to_ctrl(pkey, params) > 0;
#endif
}
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY);
return 0;
}
#ifndef FIPS_MODULE
int EVP_PKEY_get_ec_point_conv_form(const EVP_PKEY *pkey)
{
char name[80];
size_t name_len;
if (pkey == NULL)
return 0;
if (pkey->keymgmt == NULL
|| pkey->keydata == NULL) {
# ifndef OPENSSL_NO_EC
/* Might work through the legacy route */
const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
if (ec == NULL)
return 0;
return EC_KEY_get_conv_form(ec);
# else
return 0;
# endif
}
if (!EVP_PKEY_get_utf8_string_param(pkey,
OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
name, sizeof(name), &name_len))
return 0;
if (strcmp(name, "uncompressed") == 0)
return POINT_CONVERSION_UNCOMPRESSED;
if (strcmp(name, "compressed") == 0)
return POINT_CONVERSION_COMPRESSED;
if (strcmp(name, "hybrid") == 0)
return POINT_CONVERSION_HYBRID;
return 0;
}
int EVP_PKEY_get_field_type(const EVP_PKEY *pkey)
{
char fstr[80];
size_t fstrlen;
if (pkey == NULL)
return 0;
if (pkey->keymgmt == NULL
|| pkey->keydata == NULL) {
# ifndef OPENSSL_NO_EC
/* Might work through the legacy route */
const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
const EC_GROUP *grp;
if (ec == NULL)
return 0;
grp = EC_KEY_get0_group(ec);
if (grp == NULL)
return 0;
return EC_GROUP_get_field_type(grp);
# else
return 0;
# endif
}
if (!EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_EC_FIELD_TYPE,
fstr, sizeof(fstr), &fstrlen))
return 0;
if (strcmp(fstr, SN_X9_62_prime_field) == 0)
return NID_X9_62_prime_field;
else if (strcmp(fstr, SN_X9_62_characteristic_two_field))
return NID_X9_62_characteristic_two_field;
return 0;
}
#endif
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index da367ed05fbe..ce6e1a1ccbd5 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -1,2056 +1,2068 @@
/*
- * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/*
* Low level key APIs (DH etc) are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <stdio.h>
#include <stdlib.h>
#ifndef FIPS_MODULE
# include <openssl/engine.h>
#endif
#include <openssl/evp.h>
#include <openssl/core_names.h>
#include <openssl/dh.h>
#include <openssl/rsa.h>
#include <openssl/kdf.h>
#include "internal/cryptlib.h"
#ifndef FIPS_MODULE
# include "crypto/asn1.h"
#endif
#include "crypto/evp.h"
#include "crypto/dh.h"
#include "crypto/ec.h"
#include "internal/ffc.h"
#include "internal/numbers.h"
#include "internal/provider.h"
#include "evp_local.h"
#ifndef FIPS_MODULE
static int evp_pkey_ctx_store_cached_data(EVP_PKEY_CTX *ctx,
int keytype, int optype,
int cmd, const char *name,
const void *data, size_t data_len);
static void evp_pkey_ctx_free_cached_data(EVP_PKEY_CTX *ctx,
int cmd, const char *name);
static void evp_pkey_ctx_free_all_cached_data(EVP_PKEY_CTX *ctx);
typedef const EVP_PKEY_METHOD *(*pmeth_fn)(void);
typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
static STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL;
/* This array needs to be in order of NIDs */
static pmeth_fn standard_methods[] = {
ossl_rsa_pkey_method,
# ifndef OPENSSL_NO_DH
ossl_dh_pkey_method,
# endif
# ifndef OPENSSL_NO_DSA
ossl_dsa_pkey_method,
# endif
# ifndef OPENSSL_NO_EC
ossl_ec_pkey_method,
# endif
ossl_rsa_pss_pkey_method,
# ifndef OPENSSL_NO_DH
ossl_dhx_pkey_method,
# endif
# ifndef OPENSSL_NO_EC
ossl_ecx25519_pkey_method,
ossl_ecx448_pkey_method,
# endif
# ifndef OPENSSL_NO_EC
ossl_ed25519_pkey_method,
ossl_ed448_pkey_method,
# endif
};
DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, pmeth_fn, pmeth_func);
static int pmeth_func_cmp(const EVP_PKEY_METHOD *const *a, pmeth_fn const *b)
{
return ((*a)->pkey_id - ((**b)())->pkey_id);
}
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, pmeth_fn, pmeth_func);
static int pmeth_cmp(const EVP_PKEY_METHOD *const *a,
const EVP_PKEY_METHOD *const *b)
{
return ((*a)->pkey_id - (*b)->pkey_id);
}
static const EVP_PKEY_METHOD *evp_pkey_meth_find_added_by_application(int type)
{
if (app_pkey_methods != NULL) {
int idx;
EVP_PKEY_METHOD tmp;
tmp.pkey_id = type;
idx = sk_EVP_PKEY_METHOD_find(app_pkey_methods, &tmp);
if (idx >= 0)
return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx);
}
return NULL;
}
const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type)
{
pmeth_fn *ret;
EVP_PKEY_METHOD tmp;
const EVP_PKEY_METHOD *t;
if ((t = evp_pkey_meth_find_added_by_application(type)) != NULL)
return t;
tmp.pkey_id = type;
t = &tmp;
ret = OBJ_bsearch_pmeth_func(&t, standard_methods,
OSSL_NELEM(standard_methods));
if (ret == NULL || *ret == NULL)
return NULL;
return (**ret)();
}
EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags)
{
EVP_PKEY_METHOD *pmeth;
pmeth = OPENSSL_zalloc(sizeof(*pmeth));
if (pmeth == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return NULL;
}
pmeth->pkey_id = id;
pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC;
return pmeth;
}
static void help_get_legacy_alg_type_from_keymgmt(const char *keytype,
void *arg)
{
int *type = arg;
if (*type == NID_undef)
*type = evp_pkey_name2type(keytype);
}
static int get_legacy_alg_type_from_keymgmt(const EVP_KEYMGMT *keymgmt)
{
int type = NID_undef;
EVP_KEYMGMT_names_do_all(keymgmt, help_get_legacy_alg_type_from_keymgmt,
&type);
return type;
}
#endif /* FIPS_MODULE */
int evp_pkey_ctx_state(const EVP_PKEY_CTX *ctx)
{
if (ctx->operation == EVP_PKEY_OP_UNDEFINED)
return EVP_PKEY_STATE_UNKNOWN;
if ((EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
&& ctx->op.kex.algctx != NULL)
|| (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
&& ctx->op.sig.algctx != NULL)
|| (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
&& ctx->op.ciph.algctx != NULL)
|| (EVP_PKEY_CTX_IS_GEN_OP(ctx)
&& ctx->op.keymgmt.genctx != NULL)
|| (EVP_PKEY_CTX_IS_KEM_OP(ctx)
&& ctx->op.encap.algctx != NULL))
return EVP_PKEY_STATE_PROVIDER;
return EVP_PKEY_STATE_LEGACY;
}
static EVP_PKEY_CTX *int_ctx_new(OSSL_LIB_CTX *libctx,
EVP_PKEY *pkey, ENGINE *e,
const char *keytype, const char *propquery,
int id)
{
EVP_PKEY_CTX *ret = NULL;
const EVP_PKEY_METHOD *pmeth = NULL, *app_pmeth = NULL;
EVP_KEYMGMT *keymgmt = NULL;
/* Code below to be removed when legacy support is dropped. */
/* BEGIN legacy */
if (id == -1) {
if (pkey != NULL && !evp_pkey_is_provided(pkey)) {
id = pkey->type;
} else {
if (pkey != NULL) {
/* Must be provided if we get here */
keytype = EVP_KEYMGMT_get0_name(pkey->keymgmt);
}
#ifndef FIPS_MODULE
if (keytype != NULL) {
id = evp_pkey_name2type(keytype);
if (id == NID_undef)
id = -1;
}
#endif
}
}
/* If no ID was found here, we can only resort to find a keymgmt */
if (id == -1) {
#ifndef FIPS_MODULE
/* Using engine with a key without id will not work */
if (e != NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_ALGORITHM);
return NULL;
}
#endif
goto common;
}
#ifndef FIPS_MODULE
/*
* Here, we extract what information we can for the purpose of
* supporting usage with implementations from providers, to make
* for a smooth transition from legacy stuff to provider based stuff.
*
* If an engine is given, this is entirely legacy, and we should not
* pretend anything else, so we clear the name.
*/
if (e != NULL)
keytype = NULL;
if (e == NULL && (pkey == NULL || pkey->foreign == 0))
keytype = OBJ_nid2sn(id);
# ifndef OPENSSL_NO_ENGINE
if (e == NULL && pkey != NULL)
e = pkey->pmeth_engine != NULL ? pkey->pmeth_engine : pkey->engine;
/* Try to find an ENGINE which implements this method */
if (e != NULL) {
if (!ENGINE_init(e)) {
ERR_raise(ERR_LIB_EVP, ERR_R_ENGINE_LIB);
return NULL;
}
} else {
e = ENGINE_get_pkey_meth_engine(id);
}
/*
* If an ENGINE handled this method look it up. Otherwise use internal
* tables.
*/
if (e != NULL)
pmeth = ENGINE_get_pkey_meth(e, id);
else if (pkey != NULL && pkey->foreign)
pmeth = EVP_PKEY_meth_find(id);
else
# endif
app_pmeth = pmeth = evp_pkey_meth_find_added_by_application(id);
/* END legacy */
#endif /* FIPS_MODULE */
common:
/*
* If there's no engine and no app supplied pmeth and there's a name, we try
* fetching a provider implementation.
*/
if (e == NULL && app_pmeth == NULL && keytype != NULL) {
/*
* If |pkey| is given and is provided, we take a reference to its
* keymgmt. Otherwise, we fetch one for the keytype we got. This
* is to ensure that operation init functions can access what they
* need through this single pointer.
*/
if (pkey != NULL && pkey->keymgmt != NULL) {
if (!EVP_KEYMGMT_up_ref(pkey->keymgmt))
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
else
keymgmt = pkey->keymgmt;
} else {
keymgmt = EVP_KEYMGMT_fetch(libctx, keytype, propquery);
}
if (keymgmt == NULL)
return NULL; /* EVP_KEYMGMT_fetch() recorded an error */
#ifndef FIPS_MODULE
/*
* Chase down the legacy NID, as that might be needed for diverse
* purposes, such as ensure that EVP_PKEY_type() can return sensible
* values. We go through all keymgmt names, because the keytype
* that's passed to this function doesn't necessarily translate
* directly.
*/
if (keymgmt != NULL) {
int tmp_id = get_legacy_alg_type_from_keymgmt(keymgmt);
if (tmp_id != NID_undef) {
if (id == -1) {
id = tmp_id;
} else {
/*
* It really really shouldn't differ. If it still does,
* something is very wrong.
*/
if (!ossl_assert(id == tmp_id)) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
EVP_KEYMGMT_free(keymgmt);
return NULL;
}
}
}
}
#endif
}
if (pmeth == NULL && keymgmt == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_ALGORITHM);
} else {
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL)
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
}
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
if ((ret == NULL || pmeth == NULL) && e != NULL)
ENGINE_finish(e);
#endif
if (ret == NULL) {
EVP_KEYMGMT_free(keymgmt);
return NULL;
}
if (propquery != NULL) {
ret->propquery = OPENSSL_strdup(propquery);
if (ret->propquery == NULL) {
OPENSSL_free(ret);
EVP_KEYMGMT_free(keymgmt);
return NULL;
}
}
ret->libctx = libctx;
ret->keytype = keytype;
ret->keymgmt = keymgmt;
ret->legacy_keytype = id;
ret->engine = e;
ret->pmeth = pmeth;
ret->operation = EVP_PKEY_OP_UNDEFINED;
ret->pkey = pkey;
if (pkey != NULL)
EVP_PKEY_up_ref(pkey);
if (pmeth != NULL && pmeth->init != NULL) {
if (pmeth->init(ret) <= 0) {
ret->pmeth = NULL;
EVP_PKEY_CTX_free(ret);
return NULL;
}
}
return ret;
}
/*- All methods below can also be used in FIPS_MODULE */
EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OSSL_LIB_CTX *libctx,
const char *name,
const char *propquery)
{
return int_ctx_new(libctx, NULL, NULL, name, propquery, -1);
}
EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OSSL_LIB_CTX *libctx, EVP_PKEY *pkey,
const char *propquery)
{
return int_ctx_new(libctx, pkey, NULL, NULL, propquery, -1);
}
void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx)
{
if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
if (ctx->op.sig.algctx != NULL && ctx->op.sig.signature != NULL)
ctx->op.sig.signature->freectx(ctx->op.sig.algctx);
EVP_SIGNATURE_free(ctx->op.sig.signature);
ctx->op.sig.algctx = NULL;
ctx->op.sig.signature = NULL;
} else if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
if (ctx->op.kex.algctx != NULL && ctx->op.kex.exchange != NULL)
ctx->op.kex.exchange->freectx(ctx->op.kex.algctx);
EVP_KEYEXCH_free(ctx->op.kex.exchange);
ctx->op.kex.algctx = NULL;
ctx->op.kex.exchange = NULL;
} else if (EVP_PKEY_CTX_IS_KEM_OP(ctx)) {
if (ctx->op.encap.algctx != NULL && ctx->op.encap.kem != NULL)
ctx->op.encap.kem->freectx(ctx->op.encap.algctx);
EVP_KEM_free(ctx->op.encap.kem);
ctx->op.encap.algctx = NULL;
ctx->op.encap.kem = NULL;
}
else if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) {
if (ctx->op.ciph.algctx != NULL && ctx->op.ciph.cipher != NULL)
ctx->op.ciph.cipher->freectx(ctx->op.ciph.algctx);
EVP_ASYM_CIPHER_free(ctx->op.ciph.cipher);
ctx->op.ciph.algctx = NULL;
ctx->op.ciph.cipher = NULL;
} else if (EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
if (ctx->op.keymgmt.genctx != NULL && ctx->keymgmt != NULL)
evp_keymgmt_gen_cleanup(ctx->keymgmt, ctx->op.keymgmt.genctx);
}
}
void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
{
if (ctx == NULL)
return;
if (ctx->pmeth && ctx->pmeth->cleanup)
ctx->pmeth->cleanup(ctx);
evp_pkey_ctx_free_old_ops(ctx);
#ifndef FIPS_MODULE
evp_pkey_ctx_free_all_cached_data(ctx);
#endif
EVP_KEYMGMT_free(ctx->keymgmt);
OPENSSL_free(ctx->propquery);
EVP_PKEY_free(ctx->pkey);
EVP_PKEY_free(ctx->peerkey);
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
ENGINE_finish(ctx->engine);
#endif
BN_free(ctx->rsa_pubexp);
OPENSSL_free(ctx);
}
#ifndef FIPS_MODULE
void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags,
const EVP_PKEY_METHOD *meth)
{
if (ppkey_id)
*ppkey_id = meth->pkey_id;
if (pflags)
*pflags = meth->flags;
}
void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src)
{
int pkey_id = dst->pkey_id;
int flags = dst->flags;
*dst = *src;
/* We only copy the function pointers so restore the other values */
dst->pkey_id = pkey_id;
dst->flags = flags;
}
void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth)
{
if (pmeth && (pmeth->flags & EVP_PKEY_FLAG_DYNAMIC))
OPENSSL_free(pmeth);
}
EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e)
{
return int_ctx_new(NULL, pkey, e, NULL, NULL, -1);
}
EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e)
{
return int_ctx_new(NULL, NULL, e, NULL, NULL, id);
}
EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx)
{
EVP_PKEY_CTX *rctx;
# ifndef OPENSSL_NO_ENGINE
/* Make sure it's safe to copy a pkey context using an ENGINE */
if (pctx->engine && !ENGINE_init(pctx->engine)) {
ERR_raise(ERR_LIB_EVP, ERR_R_ENGINE_LIB);
return 0;
}
# endif
rctx = OPENSSL_zalloc(sizeof(*rctx));
if (rctx == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (pctx->pkey != NULL)
EVP_PKEY_up_ref(pctx->pkey);
rctx->pkey = pctx->pkey;
rctx->operation = pctx->operation;
rctx->libctx = pctx->libctx;
rctx->keytype = pctx->keytype;
rctx->propquery = NULL;
if (pctx->propquery != NULL) {
rctx->propquery = OPENSSL_strdup(pctx->propquery);
if (rctx->propquery == NULL)
goto err;
}
rctx->legacy_keytype = pctx->legacy_keytype;
if (EVP_PKEY_CTX_IS_DERIVE_OP(pctx)) {
if (pctx->op.kex.exchange != NULL) {
rctx->op.kex.exchange = pctx->op.kex.exchange;
if (!EVP_KEYEXCH_up_ref(rctx->op.kex.exchange))
goto err;
}
if (pctx->op.kex.algctx != NULL) {
if (!ossl_assert(pctx->op.kex.exchange != NULL))
goto err;
- rctx->op.kex.algctx
- = pctx->op.kex.exchange->dupctx(pctx->op.kex.algctx);
+
+ if (pctx->op.kex.exchange->dupctx != NULL)
+ rctx->op.kex.algctx
+ = pctx->op.kex.exchange->dupctx(pctx->op.kex.algctx);
+
if (rctx->op.kex.algctx == NULL) {
EVP_KEYEXCH_free(rctx->op.kex.exchange);
rctx->op.kex.exchange = NULL;
goto err;
}
return rctx;
}
} else if (EVP_PKEY_CTX_IS_SIGNATURE_OP(pctx)) {
if (pctx->op.sig.signature != NULL) {
rctx->op.sig.signature = pctx->op.sig.signature;
if (!EVP_SIGNATURE_up_ref(rctx->op.sig.signature))
goto err;
}
if (pctx->op.sig.algctx != NULL) {
if (!ossl_assert(pctx->op.sig.signature != NULL))
goto err;
- rctx->op.sig.algctx
- = pctx->op.sig.signature->dupctx(pctx->op.sig.algctx);
+
+ if (pctx->op.sig.signature->dupctx != NULL)
+ rctx->op.sig.algctx
+ = pctx->op.sig.signature->dupctx(pctx->op.sig.algctx);
+
if (rctx->op.sig.algctx == NULL) {
EVP_SIGNATURE_free(rctx->op.sig.signature);
rctx->op.sig.signature = NULL;
goto err;
}
return rctx;
}
} else if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(pctx)) {
if (pctx->op.ciph.cipher != NULL) {
rctx->op.ciph.cipher = pctx->op.ciph.cipher;
if (!EVP_ASYM_CIPHER_up_ref(rctx->op.ciph.cipher))
goto err;
}
if (pctx->op.ciph.algctx != NULL) {
if (!ossl_assert(pctx->op.ciph.cipher != NULL))
goto err;
- rctx->op.ciph.algctx
- = pctx->op.ciph.cipher->dupctx(pctx->op.ciph.algctx);
+
+ if (pctx->op.ciph.cipher->dupctx != NULL)
+ rctx->op.ciph.algctx
+ = pctx->op.ciph.cipher->dupctx(pctx->op.ciph.algctx);
+
if (rctx->op.ciph.algctx == NULL) {
EVP_ASYM_CIPHER_free(rctx->op.ciph.cipher);
rctx->op.ciph.cipher = NULL;
goto err;
}
return rctx;
}
} else if (EVP_PKEY_CTX_IS_KEM_OP(pctx)) {
if (pctx->op.encap.kem != NULL) {
rctx->op.encap.kem = pctx->op.encap.kem;
if (!EVP_KEM_up_ref(rctx->op.encap.kem))
goto err;
}
if (pctx->op.encap.algctx != NULL) {
if (!ossl_assert(pctx->op.encap.kem != NULL))
goto err;
- rctx->op.encap.algctx
- = pctx->op.encap.kem->dupctx(pctx->op.encap.algctx);
+
+ if (pctx->op.encap.kem->dupctx != NULL)
+ rctx->op.encap.algctx
+ = pctx->op.encap.kem->dupctx(pctx->op.encap.algctx);
+
if (rctx->op.encap.algctx == NULL) {
EVP_KEM_free(rctx->op.encap.kem);
rctx->op.encap.kem = NULL;
goto err;
}
return rctx;
}
} else if (EVP_PKEY_CTX_IS_GEN_OP(pctx)) {
/* Not supported - This would need a gen_dupctx() to work */
goto err;
}
rctx->pmeth = pctx->pmeth;
# ifndef OPENSSL_NO_ENGINE
rctx->engine = pctx->engine;
# endif
if (pctx->peerkey != NULL)
EVP_PKEY_up_ref(pctx->peerkey);
rctx->peerkey = pctx->peerkey;
if (pctx->pmeth == NULL) {
if (rctx->operation == EVP_PKEY_OP_UNDEFINED) {
EVP_KEYMGMT *tmp_keymgmt = pctx->keymgmt;
void *provkey;
provkey = evp_pkey_export_to_provider(pctx->pkey, pctx->libctx,
&tmp_keymgmt, pctx->propquery);
if (provkey == NULL)
goto err;
if (!EVP_KEYMGMT_up_ref(tmp_keymgmt))
goto err;
EVP_KEYMGMT_free(rctx->keymgmt);
rctx->keymgmt = tmp_keymgmt;
return rctx;
}
} else if (pctx->pmeth->copy(rctx, pctx) > 0) {
return rctx;
}
err:
rctx->pmeth = NULL;
EVP_PKEY_CTX_free(rctx);
return NULL;
}
int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth)
{
if (app_pkey_methods == NULL) {
app_pkey_methods = sk_EVP_PKEY_METHOD_new(pmeth_cmp);
if (app_pkey_methods == NULL){
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
}
if (!sk_EVP_PKEY_METHOD_push(app_pkey_methods, pmeth)) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
sk_EVP_PKEY_METHOD_sort(app_pkey_methods);
return 1;
}
void evp_app_cleanup_int(void)
{
if (app_pkey_methods != NULL)
sk_EVP_PKEY_METHOD_pop_free(app_pkey_methods, EVP_PKEY_meth_free);
}
int EVP_PKEY_meth_remove(const EVP_PKEY_METHOD *pmeth)
{
const EVP_PKEY_METHOD *ret;
ret = sk_EVP_PKEY_METHOD_delete_ptr(app_pkey_methods, pmeth);
return ret == NULL ? 0 : 1;
}
size_t EVP_PKEY_meth_get_count(void)
{
size_t rv = OSSL_NELEM(standard_methods);
if (app_pkey_methods)
rv += sk_EVP_PKEY_METHOD_num(app_pkey_methods);
return rv;
}
const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx)
{
if (idx < OSSL_NELEM(standard_methods))
return (standard_methods[idx])();
if (app_pkey_methods == NULL)
return NULL;
idx -= OSSL_NELEM(standard_methods);
if (idx >= (size_t)sk_EVP_PKEY_METHOD_num(app_pkey_methods))
return NULL;
return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx);
}
#endif
int EVP_PKEY_CTX_is_a(EVP_PKEY_CTX *ctx, const char *keytype)
{
#ifndef FIPS_MODULE
if (evp_pkey_ctx_is_legacy(ctx))
return (ctx->pmeth->pkey_id == evp_pkey_name2type(keytype));
#endif
return EVP_KEYMGMT_is_a(ctx->keymgmt, keytype);
}
int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, const OSSL_PARAM *params)
{
switch (evp_pkey_ctx_state(ctx)) {
case EVP_PKEY_STATE_PROVIDER:
if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
&& ctx->op.kex.exchange != NULL
&& ctx->op.kex.exchange->set_ctx_params != NULL)
return
ctx->op.kex.exchange->set_ctx_params(ctx->op.kex.algctx,
params);
if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
&& ctx->op.sig.signature != NULL
&& ctx->op.sig.signature->set_ctx_params != NULL)
return
ctx->op.sig.signature->set_ctx_params(ctx->op.sig.algctx,
params);
if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
&& ctx->op.ciph.cipher != NULL
&& ctx->op.ciph.cipher->set_ctx_params != NULL)
return
ctx->op.ciph.cipher->set_ctx_params(ctx->op.ciph.algctx,
params);
if (EVP_PKEY_CTX_IS_GEN_OP(ctx)
&& ctx->keymgmt != NULL
&& ctx->keymgmt->gen_set_params != NULL)
return
evp_keymgmt_gen_set_params(ctx->keymgmt, ctx->op.keymgmt.genctx,
params);
if (EVP_PKEY_CTX_IS_KEM_OP(ctx)
&& ctx->op.encap.kem != NULL
&& ctx->op.encap.kem->set_ctx_params != NULL)
return
ctx->op.encap.kem->set_ctx_params(ctx->op.encap.algctx,
params);
break;
#ifndef FIPS_MODULE
case EVP_PKEY_STATE_UNKNOWN:
case EVP_PKEY_STATE_LEGACY:
return evp_pkey_ctx_set_params_to_ctrl(ctx, params);
#endif
}
return 0;
}
int EVP_PKEY_CTX_get_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
{
switch (evp_pkey_ctx_state(ctx)) {
case EVP_PKEY_STATE_PROVIDER:
if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
&& ctx->op.kex.exchange != NULL
&& ctx->op.kex.exchange->get_ctx_params != NULL)
return
ctx->op.kex.exchange->get_ctx_params(ctx->op.kex.algctx,
params);
if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
&& ctx->op.sig.signature != NULL
&& ctx->op.sig.signature->get_ctx_params != NULL)
return
ctx->op.sig.signature->get_ctx_params(ctx->op.sig.algctx,
params);
if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
&& ctx->op.ciph.cipher != NULL
&& ctx->op.ciph.cipher->get_ctx_params != NULL)
return
ctx->op.ciph.cipher->get_ctx_params(ctx->op.ciph.algctx,
params);
if (EVP_PKEY_CTX_IS_KEM_OP(ctx)
&& ctx->op.encap.kem != NULL
&& ctx->op.encap.kem->get_ctx_params != NULL)
return
ctx->op.encap.kem->get_ctx_params(ctx->op.encap.algctx,
params);
break;
#ifndef FIPS_MODULE
case EVP_PKEY_STATE_UNKNOWN:
case EVP_PKEY_STATE_LEGACY:
return evp_pkey_ctx_get_params_to_ctrl(ctx, params);
#endif
}
return 0;
}
#ifndef FIPS_MODULE
const OSSL_PARAM *EVP_PKEY_CTX_gettable_params(const EVP_PKEY_CTX *ctx)
{
void *provctx;
if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
&& ctx->op.kex.exchange != NULL
&& ctx->op.kex.exchange->gettable_ctx_params != NULL) {
provctx = ossl_provider_ctx(EVP_KEYEXCH_get0_provider(ctx->op.kex.exchange));
return ctx->op.kex.exchange->gettable_ctx_params(ctx->op.kex.algctx,
provctx);
}
if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
&& ctx->op.sig.signature != NULL
&& ctx->op.sig.signature->gettable_ctx_params != NULL) {
provctx = ossl_provider_ctx(
EVP_SIGNATURE_get0_provider(ctx->op.sig.signature));
return ctx->op.sig.signature->gettable_ctx_params(ctx->op.sig.algctx,
provctx);
}
if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
&& ctx->op.ciph.cipher != NULL
&& ctx->op.ciph.cipher->gettable_ctx_params != NULL) {
provctx = ossl_provider_ctx(
EVP_ASYM_CIPHER_get0_provider(ctx->op.ciph.cipher));
return ctx->op.ciph.cipher->gettable_ctx_params(ctx->op.ciph.algctx,
provctx);
}
if (EVP_PKEY_CTX_IS_KEM_OP(ctx)
&& ctx->op.encap.kem != NULL
&& ctx->op.encap.kem->gettable_ctx_params != NULL) {
provctx = ossl_provider_ctx(EVP_KEM_get0_provider(ctx->op.encap.kem));
return ctx->op.encap.kem->gettable_ctx_params(ctx->op.encap.algctx,
provctx);
}
return NULL;
}
const OSSL_PARAM *EVP_PKEY_CTX_settable_params(const EVP_PKEY_CTX *ctx)
{
void *provctx;
if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
&& ctx->op.kex.exchange != NULL
&& ctx->op.kex.exchange->settable_ctx_params != NULL) {
provctx = ossl_provider_ctx(EVP_KEYEXCH_get0_provider(ctx->op.kex.exchange));
return ctx->op.kex.exchange->settable_ctx_params(ctx->op.kex.algctx,
provctx);
}
if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
&& ctx->op.sig.signature != NULL
&& ctx->op.sig.signature->settable_ctx_params != NULL) {
provctx = ossl_provider_ctx(
EVP_SIGNATURE_get0_provider(ctx->op.sig.signature));
return ctx->op.sig.signature->settable_ctx_params(ctx->op.sig.algctx,
provctx);
}
if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
&& ctx->op.ciph.cipher != NULL
&& ctx->op.ciph.cipher->settable_ctx_params != NULL) {
provctx = ossl_provider_ctx(
EVP_ASYM_CIPHER_get0_provider(ctx->op.ciph.cipher));
return ctx->op.ciph.cipher->settable_ctx_params(ctx->op.ciph.algctx,
provctx);
}
if (EVP_PKEY_CTX_IS_GEN_OP(ctx)
&& ctx->keymgmt != NULL
&& ctx->keymgmt->gen_settable_params != NULL) {
provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(ctx->keymgmt));
return ctx->keymgmt->gen_settable_params(ctx->op.keymgmt.genctx,
provctx);
}
if (EVP_PKEY_CTX_IS_KEM_OP(ctx)
&& ctx->op.encap.kem != NULL
&& ctx->op.encap.kem->settable_ctx_params != NULL) {
provctx = ossl_provider_ctx(EVP_KEM_get0_provider(ctx->op.encap.kem));
return ctx->op.encap.kem->settable_ctx_params(ctx->op.encap.algctx,
provctx);
}
return NULL;
}
/*
* Internal helpers for stricter EVP_PKEY_CTX_{set,get}_params().
*
* Return 1 on success, 0 or negative for errors.
*
* In particular they return -2 if any of the params is not supported.
*
* They are not available in FIPS_MODULE as they depend on
* - EVP_PKEY_CTX_{get,set}_params()
* - EVP_PKEY_CTX_{gettable,settable}_params()
*
*/
int evp_pkey_ctx_set_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
{
if (ctx == NULL || params == NULL)
return 0;
/*
* We only check for provider side EVP_PKEY_CTX. For #legacy, we
* depend on the translation that happens in EVP_PKEY_CTX_set_params()
* call, and that the resulting ctrl call will return -2 if it doesn't
* known the ctrl command number.
*/
if (evp_pkey_ctx_is_provided(ctx)) {
const OSSL_PARAM *settable = EVP_PKEY_CTX_settable_params(ctx);
const OSSL_PARAM *p;
for (p = params; p->key != NULL; p++) {
/* Check the ctx actually understands this parameter */
if (OSSL_PARAM_locate_const(settable, p->key) == NULL )
return -2;
}
}
return EVP_PKEY_CTX_set_params(ctx, params);
}
int evp_pkey_ctx_get_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
{
if (ctx == NULL || params == NULL)
return 0;
/*
* We only check for provider side EVP_PKEY_CTX. For #legacy, we
* depend on the translation that happens in EVP_PKEY_CTX_get_params()
* call, and that the resulting ctrl call will return -2 if it doesn't
* known the ctrl command number.
*/
if (evp_pkey_ctx_is_provided(ctx)) {
const OSSL_PARAM *gettable = EVP_PKEY_CTX_gettable_params(ctx);
const OSSL_PARAM *p;
for (p = params; p->key != NULL; p++ ) {
/* Check the ctx actually understands this parameter */
if (OSSL_PARAM_locate_const(gettable, p->key) == NULL )
return -2;
}
}
return EVP_PKEY_CTX_get_params(ctx, params);
}
int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md)
{
OSSL_PARAM sig_md_params[2], *p = sig_md_params;
/* 80 should be big enough */
char name[80] = "";
const EVP_MD *tmp;
if (ctx == NULL || !EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
if (ctx->op.sig.algctx == NULL)
return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_GET_MD, 0, (void *)(md));
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST,
name,
sizeof(name));
*p = OSSL_PARAM_construct_end();
if (!EVP_PKEY_CTX_get_params(ctx, sig_md_params))
return 0;
tmp = evp_get_digestbyname_ex(ctx->libctx, name);
if (tmp == NULL)
return 0;
*md = tmp;
return 1;
}
static int evp_pkey_ctx_set_md(EVP_PKEY_CTX *ctx, const EVP_MD *md,
int fallback, const char *param, int op,
int ctrl)
{
OSSL_PARAM md_params[2], *p = md_params;
const char *name;
if (ctx == NULL || (ctx->operation & op) == 0) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
if (fallback)
return EVP_PKEY_CTX_ctrl(ctx, -1, op, ctrl, 0, (void *)(md));
if (md == NULL) {
name = "";
} else {
name = EVP_MD_get0_name(md);
}
*p++ = OSSL_PARAM_construct_utf8_string(param,
/*
* Cast away the const. This is read
* only so should be safe
*/
(char *)name, 0);
*p = OSSL_PARAM_construct_end();
return EVP_PKEY_CTX_set_params(ctx, md_params);
}
int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
{
return evp_pkey_ctx_set_md(ctx, md, ctx->op.sig.algctx == NULL,
OSSL_SIGNATURE_PARAM_DIGEST,
EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD);
}
int EVP_PKEY_CTX_set_tls1_prf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
{
return evp_pkey_ctx_set_md(ctx, md, ctx->op.kex.algctx == NULL,
OSSL_KDF_PARAM_DIGEST,
EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_TLS_MD);
}
static int evp_pkey_ctx_set1_octet_string(EVP_PKEY_CTX *ctx, int fallback,
const char *param, int op, int ctrl,
const unsigned char *data,
int datalen)
{
OSSL_PARAM octet_string_params[2], *p = octet_string_params;
if (ctx == NULL || (ctx->operation & op) == 0) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
/* Code below to be removed when legacy support is dropped. */
if (fallback)
return EVP_PKEY_CTX_ctrl(ctx, -1, op, ctrl, datalen, (void *)(data));
/* end of legacy support */
if (datalen < 0) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_LENGTH);
return 0;
}
*p++ = OSSL_PARAM_construct_octet_string(param,
/*
* Cast away the const. This is read
* only so should be safe
*/
(unsigned char *)data,
(size_t)datalen);
*p = OSSL_PARAM_construct_end();
return EVP_PKEY_CTX_set_params(ctx, octet_string_params);
}
int EVP_PKEY_CTX_set1_tls1_prf_secret(EVP_PKEY_CTX *ctx,
const unsigned char *sec, int seclen)
{
return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
OSSL_KDF_PARAM_SECRET,
EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_TLS_SECRET,
sec, seclen);
}
int EVP_PKEY_CTX_add1_tls1_prf_seed(EVP_PKEY_CTX *ctx,
const unsigned char *seed, int seedlen)
{
return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
OSSL_KDF_PARAM_SEED,
EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_TLS_SEED,
seed, seedlen);
}
int EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
{
return evp_pkey_ctx_set_md(ctx, md, ctx->op.kex.algctx == NULL,
OSSL_KDF_PARAM_DIGEST,
EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_MD);
}
int EVP_PKEY_CTX_set1_hkdf_salt(EVP_PKEY_CTX *ctx,
const unsigned char *salt, int saltlen)
{
return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
OSSL_KDF_PARAM_SALT,
EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_HKDF_SALT,
salt, saltlen);
}
int EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *ctx,
const unsigned char *key, int keylen)
{
return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
OSSL_KDF_PARAM_KEY,
EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_HKDF_KEY,
key, keylen);
}
int EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *ctx,
const unsigned char *info, int infolen)
{
return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
OSSL_KDF_PARAM_INFO,
EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_HKDF_INFO,
info, infolen);
}
int EVP_PKEY_CTX_set_hkdf_mode(EVP_PKEY_CTX *ctx, int mode)
{
OSSL_PARAM int_params[2], *p = int_params;
if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
/* Code below to be removed when legacy support is dropped. */
if (ctx->op.kex.algctx == NULL)
return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_HKDF_MODE, mode, NULL);
/* end of legacy support */
if (mode < 0) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
return 0;
}
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
*p = OSSL_PARAM_construct_end();
return EVP_PKEY_CTX_set_params(ctx, int_params);
}
int EVP_PKEY_CTX_set1_pbe_pass(EVP_PKEY_CTX *ctx, const char *pass,
int passlen)
{
return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
OSSL_KDF_PARAM_PASSWORD,
EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_PASS,
(const unsigned char *)pass, passlen);
}
int EVP_PKEY_CTX_set1_scrypt_salt(EVP_PKEY_CTX *ctx,
const unsigned char *salt, int saltlen)
{
return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.algctx == NULL,
OSSL_KDF_PARAM_SALT,
EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_SCRYPT_SALT,
salt, saltlen);
}
static int evp_pkey_ctx_set_uint64(EVP_PKEY_CTX *ctx, const char *param,
int op, int ctrl, uint64_t val)
{
OSSL_PARAM uint64_params[2], *p = uint64_params;
if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
/* Code below to be removed when legacy support is dropped. */
if (ctx->op.kex.algctx == NULL)
return EVP_PKEY_CTX_ctrl_uint64(ctx, -1, op, ctrl, val);
/* end of legacy support */
*p++ = OSSL_PARAM_construct_uint64(param, &val);
*p = OSSL_PARAM_construct_end();
return EVP_PKEY_CTX_set_params(ctx, uint64_params);
}
int EVP_PKEY_CTX_set_scrypt_N(EVP_PKEY_CTX *ctx, uint64_t n)
{
return evp_pkey_ctx_set_uint64(ctx, OSSL_KDF_PARAM_SCRYPT_N,
EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_SCRYPT_N,
n);
}
int EVP_PKEY_CTX_set_scrypt_r(EVP_PKEY_CTX *ctx, uint64_t r)
{
return evp_pkey_ctx_set_uint64(ctx, OSSL_KDF_PARAM_SCRYPT_R,
EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_SCRYPT_R,
r);
}
int EVP_PKEY_CTX_set_scrypt_p(EVP_PKEY_CTX *ctx, uint64_t p)
{
return evp_pkey_ctx_set_uint64(ctx, OSSL_KDF_PARAM_SCRYPT_P,
EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_SCRYPT_P,
p);
}
int EVP_PKEY_CTX_set_scrypt_maxmem_bytes(EVP_PKEY_CTX *ctx,
uint64_t maxmem_bytes)
{
return evp_pkey_ctx_set_uint64(ctx, OSSL_KDF_PARAM_SCRYPT_MAXMEM,
EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES,
maxmem_bytes);
}
int EVP_PKEY_CTX_set_mac_key(EVP_PKEY_CTX *ctx, const unsigned char *key,
int keylen)
{
return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.keymgmt.genctx == NULL,
OSSL_PKEY_PARAM_PRIV_KEY,
EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_SET_MAC_KEY,
key, keylen);
}
int EVP_PKEY_CTX_set_kem_op(EVP_PKEY_CTX *ctx, const char *op)
{
OSSL_PARAM params[2], *p = params;
if (ctx == NULL || op == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
return 0;
}
if (!EVP_PKEY_CTX_IS_KEM_OP(ctx)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KEM_PARAM_OPERATION,
(char *)op, 0);
*p = OSSL_PARAM_construct_end();
return EVP_PKEY_CTX_set_params(ctx, params);
}
int evp_pkey_ctx_set1_id_prov(EVP_PKEY_CTX *ctx, const void *id, int len)
{
OSSL_PARAM params[2], *p = params;
int ret;
if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
*p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DIST_ID,
/*
* Cast away the const. This is
* read only so should be safe
*/
(void *)id, (size_t)len);
*p++ = OSSL_PARAM_construct_end();
ret = evp_pkey_ctx_set_params_strict(ctx, params);
if (ret == -2)
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return ret;
}
int EVP_PKEY_CTX_set1_id(EVP_PKEY_CTX *ctx, const void *id, int len)
{
return EVP_PKEY_CTX_ctrl(ctx, -1, -1,
EVP_PKEY_CTRL_SET1_ID, (int)len, (void*)(id));
}
static int get1_id_data(EVP_PKEY_CTX *ctx, void *id, size_t *id_len)
{
int ret;
void *tmp_id = NULL;
OSSL_PARAM params[2], *p = params;
if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
*p++ = OSSL_PARAM_construct_octet_ptr(OSSL_PKEY_PARAM_DIST_ID,
&tmp_id, 0);
*p++ = OSSL_PARAM_construct_end();
ret = evp_pkey_ctx_get_params_strict(ctx, params);
if (ret == -2) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
} else if (ret > 0) {
size_t tmp_id_len = params[0].return_size;
if (id != NULL)
memcpy(id, tmp_id, tmp_id_len);
if (id_len != NULL)
*id_len = tmp_id_len;
}
return ret;
}
int evp_pkey_ctx_get1_id_prov(EVP_PKEY_CTX *ctx, void *id)
{
return get1_id_data(ctx, id, NULL);
}
int evp_pkey_ctx_get1_id_len_prov(EVP_PKEY_CTX *ctx, size_t *id_len)
{
return get1_id_data(ctx, NULL, id_len);
}
int EVP_PKEY_CTX_get1_id(EVP_PKEY_CTX *ctx, void *id)
{
return EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_GET1_ID, 0, (void*)id);
}
int EVP_PKEY_CTX_get1_id_len(EVP_PKEY_CTX *ctx, size_t *id_len)
{
return EVP_PKEY_CTX_ctrl(ctx, -1, -1,
EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)id_len);
}
static int evp_pkey_ctx_ctrl_int(EVP_PKEY_CTX *ctx, int keytype, int optype,
int cmd, int p1, void *p2)
{
int ret = 0;
/*
* If the method has a |digest_custom| function, we can relax the
* operation type check, since this can be called before the operation
* is initialized.
*/
if (ctx->pmeth == NULL || ctx->pmeth->digest_custom == NULL) {
if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
ERR_raise(ERR_LIB_EVP, EVP_R_NO_OPERATION_SET);
return -1;
}
if ((optype != -1) && !(ctx->operation & optype)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
return -1;
}
}
switch (evp_pkey_ctx_state(ctx)) {
case EVP_PKEY_STATE_PROVIDER:
return evp_pkey_ctx_ctrl_to_param(ctx, keytype, optype, cmd, p1, p2);
case EVP_PKEY_STATE_UNKNOWN:
case EVP_PKEY_STATE_LEGACY:
if (ctx->pmeth == NULL || ctx->pmeth->ctrl == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype))
return -1;
ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
if (ret == -2)
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
break;
}
return ret;
}
int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
int cmd, int p1, void *p2)
{
int ret = 0;
if (ctx == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
/* If unsupported, we don't want that reported here */
ERR_set_mark();
ret = evp_pkey_ctx_store_cached_data(ctx, keytype, optype,
cmd, NULL, p2, p1);
if (ret == -2) {
ERR_pop_to_mark();
} else {
ERR_clear_last_mark();
/*
* If there was an error, there was an error.
* If the operation isn't initialized yet, we also return, as
* the saved values will be used then anyway.
*/
if (ret < 1 || ctx->operation == EVP_PKEY_OP_UNDEFINED)
return ret;
}
return evp_pkey_ctx_ctrl_int(ctx, keytype, optype, cmd, p1, p2);
}
int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype,
int cmd, uint64_t value)
{
return EVP_PKEY_CTX_ctrl(ctx, keytype, optype, cmd, 0, &value);
}
static int evp_pkey_ctx_ctrl_str_int(EVP_PKEY_CTX *ctx,
const char *name, const char *value)
{
int ret = 0;
if (ctx == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
switch (evp_pkey_ctx_state(ctx)) {
case EVP_PKEY_STATE_PROVIDER:
return evp_pkey_ctx_ctrl_str_to_param(ctx, name, value);
case EVP_PKEY_STATE_UNKNOWN:
case EVP_PKEY_STATE_LEGACY:
if (ctx == NULL || ctx->pmeth == NULL || ctx->pmeth->ctrl_str == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
if (strcmp(name, "digest") == 0)
ret = EVP_PKEY_CTX_md(ctx,
EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_CTRL_MD, value);
else
ret = ctx->pmeth->ctrl_str(ctx, name, value);
break;
}
return ret;
}
int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
const char *name, const char *value)
{
int ret = 0;
/* If unsupported, we don't want that reported here */
ERR_set_mark();
ret = evp_pkey_ctx_store_cached_data(ctx, -1, -1, -1,
name, value, strlen(value) + 1);
if (ret == -2) {
ERR_pop_to_mark();
} else {
ERR_clear_last_mark();
/*
* If there was an error, there was an error.
* If the operation isn't initialized yet, we also return, as
* the saved values will be used then anyway.
*/
if (ret < 1 || ctx->operation == EVP_PKEY_OP_UNDEFINED)
return ret;
}
return evp_pkey_ctx_ctrl_str_int(ctx, name, value);
}
static int decode_cmd(int cmd, const char *name)
{
if (cmd == -1) {
/*
* The consequence of the assertion not being true is that this
* function will return -1, which will cause the calling functions
* to signal that the command is unsupported... in non-debug mode.
*/
if (ossl_assert(name != NULL))
if (strcmp(name, "distid") == 0 || strcmp(name, "hexdistid") == 0)
cmd = EVP_PKEY_CTRL_SET1_ID;
}
return cmd;
}
static int evp_pkey_ctx_store_cached_data(EVP_PKEY_CTX *ctx,
int keytype, int optype,
int cmd, const char *name,
const void *data, size_t data_len)
{
/*
* Check that it's one of the supported commands. The ctrl commands
* number cases here must correspond to the cases in the bottom switch
* in this function.
*/
switch (cmd = decode_cmd(cmd, name)) {
case EVP_PKEY_CTRL_SET1_ID:
break;
default:
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
if (keytype != -1) {
switch (evp_pkey_ctx_state(ctx)) {
case EVP_PKEY_STATE_PROVIDER:
if (ctx->keymgmt == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
if (!EVP_KEYMGMT_is_a(ctx->keymgmt,
evp_pkey_type2name(keytype))) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
return -1;
}
break;
case EVP_PKEY_STATE_UNKNOWN:
case EVP_PKEY_STATE_LEGACY:
if (ctx->pmeth == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
if (EVP_PKEY_type(ctx->pmeth->pkey_id) != EVP_PKEY_type(keytype)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
return -1;
}
break;
}
}
if (optype != -1 && (ctx->operation & optype) == 0) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
return -1;
}
switch (cmd) {
case EVP_PKEY_CTRL_SET1_ID:
evp_pkey_ctx_free_cached_data(ctx, cmd, name);
if (name != NULL) {
ctx->cached_parameters.dist_id_name = OPENSSL_strdup(name);
if (ctx->cached_parameters.dist_id_name == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
}
if (data_len > 0) {
ctx->cached_parameters.dist_id = OPENSSL_memdup(data, data_len);
if (ctx->cached_parameters.dist_id == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
}
ctx->cached_parameters.dist_id_set = 1;
ctx->cached_parameters.dist_id_len = data_len;
break;
}
return 1;
}
static void evp_pkey_ctx_free_cached_data(EVP_PKEY_CTX *ctx,
int cmd, const char *name)
{
cmd = decode_cmd(cmd, name);
switch (cmd) {
case EVP_PKEY_CTRL_SET1_ID:
OPENSSL_free(ctx->cached_parameters.dist_id);
OPENSSL_free(ctx->cached_parameters.dist_id_name);
ctx->cached_parameters.dist_id = NULL;
ctx->cached_parameters.dist_id_name = NULL;
break;
}
}
static void evp_pkey_ctx_free_all_cached_data(EVP_PKEY_CTX *ctx)
{
evp_pkey_ctx_free_cached_data(ctx, EVP_PKEY_CTRL_SET1_ID, NULL);
}
int evp_pkey_ctx_use_cached_data(EVP_PKEY_CTX *ctx)
{
int ret = 1;
if (ret && ctx->cached_parameters.dist_id_set) {
const char *name = ctx->cached_parameters.dist_id_name;
const void *val = ctx->cached_parameters.dist_id;
size_t len = ctx->cached_parameters.dist_id_len;
if (name != NULL)
ret = evp_pkey_ctx_ctrl_str_int(ctx, name, val);
else
ret = evp_pkey_ctx_ctrl_int(ctx, -1, ctx->operation,
EVP_PKEY_CTRL_SET1_ID,
(int)len, (void *)val);
}
return ret;
}
OSSL_LIB_CTX *EVP_PKEY_CTX_get0_libctx(EVP_PKEY_CTX *ctx)
{
return ctx->libctx;
}
const char *EVP_PKEY_CTX_get0_propq(const EVP_PKEY_CTX *ctx)
{
return ctx->propquery;
}
const OSSL_PROVIDER *EVP_PKEY_CTX_get0_provider(const EVP_PKEY_CTX *ctx)
{
if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
if (ctx->op.sig.signature != NULL)
return EVP_SIGNATURE_get0_provider(ctx->op.sig.signature);
} else if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
if (ctx->op.kex.exchange != NULL)
return EVP_KEYEXCH_get0_provider(ctx->op.kex.exchange);
} else if (EVP_PKEY_CTX_IS_KEM_OP(ctx)) {
if (ctx->op.encap.kem != NULL)
return EVP_KEM_get0_provider(ctx->op.encap.kem);
} else if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) {
if (ctx->op.ciph.cipher != NULL)
return EVP_ASYM_CIPHER_get0_provider(ctx->op.ciph.cipher);
} else if (EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
if (ctx->keymgmt != NULL)
return EVP_KEYMGMT_get0_provider(ctx->keymgmt);
}
return NULL;
}
/* Utility functions to send a string of hex string to a ctrl */
int EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str)
{
size_t len;
len = strlen(str);
if (len > INT_MAX)
return -1;
return ctx->pmeth->ctrl(ctx, cmd, len, (void *)str);
}
int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex)
{
unsigned char *bin;
long binlen;
int rv = -1;
bin = OPENSSL_hexstr2buf(hex, &binlen);
if (bin == NULL)
return 0;
if (binlen <= INT_MAX)
rv = ctx->pmeth->ctrl(ctx, cmd, binlen, bin);
OPENSSL_free(bin);
return rv;
}
/* Pass a message digest to a ctrl */
int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md)
{
const EVP_MD *m;
if (md == NULL || (m = EVP_get_digestbyname(md)) == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_DIGEST);
return 0;
}
return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, 0, (void *)m);
}
int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx)
{
return ctx->operation;
}
void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen)
{
ctx->keygen_info = dat;
ctx->keygen_info_count = datlen;
}
void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data)
{
ctx->data = data;
}
void *EVP_PKEY_CTX_get_data(const EVP_PKEY_CTX *ctx)
{
return ctx->data;
}
EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx)
{
return ctx->pkey;
}
EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx)
{
return ctx->peerkey;
}
void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data)
{
ctx->app_data = data;
}
void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx)
{
return ctx->app_data;
}
void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth,
int (*init) (EVP_PKEY_CTX *ctx))
{
pmeth->init = init;
}
void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth,
int (*copy) (EVP_PKEY_CTX *dst,
const EVP_PKEY_CTX *src))
{
pmeth->copy = copy;
}
void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth,
void (*cleanup) (EVP_PKEY_CTX *ctx))
{
pmeth->cleanup = cleanup;
}
void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth,
int (*paramgen_init) (EVP_PKEY_CTX *ctx),
int (*paramgen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey))
{
pmeth->paramgen_init = paramgen_init;
pmeth->paramgen = paramgen;
}
void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth,
int (*keygen_init) (EVP_PKEY_CTX *ctx),
int (*keygen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey))
{
pmeth->keygen_init = keygen_init;
pmeth->keygen = keygen;
}
void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth,
int (*sign_init) (EVP_PKEY_CTX *ctx),
int (*sign) (EVP_PKEY_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs,
size_t tbslen))
{
pmeth->sign_init = sign_init;
pmeth->sign = sign;
}
void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth,
int (*verify_init) (EVP_PKEY_CTX *ctx),
int (*verify) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
size_t siglen,
const unsigned char *tbs,
size_t tbslen))
{
pmeth->verify_init = verify_init;
pmeth->verify = verify;
}
void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth,
int (*verify_recover_init) (EVP_PKEY_CTX
*ctx),
int (*verify_recover) (EVP_PKEY_CTX
*ctx,
unsigned char
*sig,
size_t *siglen,
const unsigned
char *tbs,
size_t tbslen))
{
pmeth->verify_recover_init = verify_recover_init;
pmeth->verify_recover = verify_recover;
}
void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth,
int (*signctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (*signctx) (EVP_PKEY_CTX *ctx,
unsigned char *sig,
size_t *siglen,
EVP_MD_CTX *mctx))
{
pmeth->signctx_init = signctx_init;
pmeth->signctx = signctx;
}
void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth,
int (*verifyctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (*verifyctx) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
int siglen,
EVP_MD_CTX *mctx))
{
pmeth->verifyctx_init = verifyctx_init;
pmeth->verifyctx = verifyctx;
}
void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth,
int (*encrypt_init) (EVP_PKEY_CTX *ctx),
int (*encryptfn) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen))
{
pmeth->encrypt_init = encrypt_init;
pmeth->encrypt = encryptfn;
}
void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth,
int (*decrypt_init) (EVP_PKEY_CTX *ctx),
int (*decrypt) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen))
{
pmeth->decrypt_init = decrypt_init;
pmeth->decrypt = decrypt;
}
void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth,
int (*derive_init) (EVP_PKEY_CTX *ctx),
int (*derive) (EVP_PKEY_CTX *ctx,
unsigned char *key,
size_t *keylen))
{
pmeth->derive_init = derive_init;
pmeth->derive = derive;
}
void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
void *p2),
int (*ctrl_str) (EVP_PKEY_CTX *ctx,
const char *type,
const char *value))
{
pmeth->ctrl = ctrl;
pmeth->ctrl_str = ctrl_str;
}
void EVP_PKEY_meth_set_digestsign(EVP_PKEY_METHOD *pmeth,
int (*digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen))
{
pmeth->digestsign = digestsign;
}
void EVP_PKEY_meth_set_digestverify(EVP_PKEY_METHOD *pmeth,
int (*digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs,
size_t tbslen))
{
pmeth->digestverify = digestverify;
}
void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth,
int (*check) (EVP_PKEY *pkey))
{
pmeth->check = check;
}
void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth,
int (*check) (EVP_PKEY *pkey))
{
pmeth->public_check = check;
}
void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth,
int (*check) (EVP_PKEY *pkey))
{
pmeth->param_check = check;
}
void EVP_PKEY_meth_set_digest_custom(EVP_PKEY_METHOD *pmeth,
int (*digest_custom) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx))
{
pmeth->digest_custom = digest_custom;
}
void EVP_PKEY_meth_get_init(const EVP_PKEY_METHOD *pmeth,
int (**pinit) (EVP_PKEY_CTX *ctx))
{
*pinit = pmeth->init;
}
void EVP_PKEY_meth_get_copy(const EVP_PKEY_METHOD *pmeth,
int (**pcopy) (EVP_PKEY_CTX *dst,
const EVP_PKEY_CTX *src))
{
*pcopy = pmeth->copy;
}
void EVP_PKEY_meth_get_cleanup(const EVP_PKEY_METHOD *pmeth,
void (**pcleanup) (EVP_PKEY_CTX *ctx))
{
*pcleanup = pmeth->cleanup;
}
void EVP_PKEY_meth_get_paramgen(const EVP_PKEY_METHOD *pmeth,
int (**pparamgen_init) (EVP_PKEY_CTX *ctx),
int (**pparamgen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey))
{
if (pparamgen_init)
*pparamgen_init = pmeth->paramgen_init;
if (pparamgen)
*pparamgen = pmeth->paramgen;
}
void EVP_PKEY_meth_get_keygen(const EVP_PKEY_METHOD *pmeth,
int (**pkeygen_init) (EVP_PKEY_CTX *ctx),
int (**pkeygen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey))
{
if (pkeygen_init)
*pkeygen_init = pmeth->keygen_init;
if (pkeygen)
*pkeygen = pmeth->keygen;
}
void EVP_PKEY_meth_get_sign(const EVP_PKEY_METHOD *pmeth,
int (**psign_init) (EVP_PKEY_CTX *ctx),
int (**psign) (EVP_PKEY_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs,
size_t tbslen))
{
if (psign_init)
*psign_init = pmeth->sign_init;
if (psign)
*psign = pmeth->sign;
}
void EVP_PKEY_meth_get_verify(const EVP_PKEY_METHOD *pmeth,
int (**pverify_init) (EVP_PKEY_CTX *ctx),
int (**pverify) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
size_t siglen,
const unsigned char *tbs,
size_t tbslen))
{
if (pverify_init)
*pverify_init = pmeth->verify_init;
if (pverify)
*pverify = pmeth->verify;
}
void EVP_PKEY_meth_get_verify_recover(const EVP_PKEY_METHOD *pmeth,
int (**pverify_recover_init) (EVP_PKEY_CTX
*ctx),
int (**pverify_recover) (EVP_PKEY_CTX
*ctx,
unsigned char
*sig,
size_t *siglen,
const unsigned
char *tbs,
size_t tbslen))
{
if (pverify_recover_init)
*pverify_recover_init = pmeth->verify_recover_init;
if (pverify_recover)
*pverify_recover = pmeth->verify_recover;
}
void EVP_PKEY_meth_get_signctx(const EVP_PKEY_METHOD *pmeth,
int (**psignctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (**psignctx) (EVP_PKEY_CTX *ctx,
unsigned char *sig,
size_t *siglen,
EVP_MD_CTX *mctx))
{
if (psignctx_init)
*psignctx_init = pmeth->signctx_init;
if (psignctx)
*psignctx = pmeth->signctx;
}
void EVP_PKEY_meth_get_verifyctx(const EVP_PKEY_METHOD *pmeth,
int (**pverifyctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (**pverifyctx) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
int siglen,
EVP_MD_CTX *mctx))
{
if (pverifyctx_init)
*pverifyctx_init = pmeth->verifyctx_init;
if (pverifyctx)
*pverifyctx = pmeth->verifyctx;
}
void EVP_PKEY_meth_get_encrypt(const EVP_PKEY_METHOD *pmeth,
int (**pencrypt_init) (EVP_PKEY_CTX *ctx),
int (**pencryptfn) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen))
{
if (pencrypt_init)
*pencrypt_init = pmeth->encrypt_init;
if (pencryptfn)
*pencryptfn = pmeth->encrypt;
}
void EVP_PKEY_meth_get_decrypt(const EVP_PKEY_METHOD *pmeth,
int (**pdecrypt_init) (EVP_PKEY_CTX *ctx),
int (**pdecrypt) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen))
{
if (pdecrypt_init)
*pdecrypt_init = pmeth->decrypt_init;
if (pdecrypt)
*pdecrypt = pmeth->decrypt;
}
void EVP_PKEY_meth_get_derive(const EVP_PKEY_METHOD *pmeth,
int (**pderive_init) (EVP_PKEY_CTX *ctx),
int (**pderive) (EVP_PKEY_CTX *ctx,
unsigned char *key,
size_t *keylen))
{
if (pderive_init)
*pderive_init = pmeth->derive_init;
if (pderive)
*pderive = pmeth->derive;
}
void EVP_PKEY_meth_get_ctrl(const EVP_PKEY_METHOD *pmeth,
int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
void *p2),
int (**pctrl_str) (EVP_PKEY_CTX *ctx,
const char *type,
const char *value))
{
if (pctrl)
*pctrl = pmeth->ctrl;
if (pctrl_str)
*pctrl_str = pmeth->ctrl_str;
}
void EVP_PKEY_meth_get_digestsign(const EVP_PKEY_METHOD *pmeth,
int (**digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen))
{
if (digestsign)
*digestsign = pmeth->digestsign;
}
void EVP_PKEY_meth_get_digestverify(const EVP_PKEY_METHOD *pmeth,
int (**digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs,
size_t tbslen))
{
if (digestverify)
*digestverify = pmeth->digestverify;
}
void EVP_PKEY_meth_get_check(const EVP_PKEY_METHOD *pmeth,
int (**pcheck) (EVP_PKEY *pkey))
{
if (pcheck != NULL)
*pcheck = pmeth->check;
}
void EVP_PKEY_meth_get_public_check(const EVP_PKEY_METHOD *pmeth,
int (**pcheck) (EVP_PKEY *pkey))
{
if (pcheck != NULL)
*pcheck = pmeth->public_check;
}
void EVP_PKEY_meth_get_param_check(const EVP_PKEY_METHOD *pmeth,
int (**pcheck) (EVP_PKEY *pkey))
{
if (pcheck != NULL)
*pcheck = pmeth->param_check;
}
void EVP_PKEY_meth_get_digest_custom(const EVP_PKEY_METHOD *pmeth,
int (**pdigest_custom) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx))
{
if (pdigest_custom != NULL)
*pdigest_custom = pmeth->digest_custom;
}
#endif /* FIPS_MODULE */
diff --git a/crypto/ffc/ffc_backend.c b/crypto/ffc/ffc_backend.c
index dbd28b0e66bd..fe0a82eac8a6 100644
--- a/crypto/ffc/ffc_backend.c
+++ b/crypto/ffc/ffc_backend.c
@@ -1,129 +1,130 @@
/*
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <openssl/core_names.h>
#include "internal/ffc.h"
#include "internal/sizes.h"
/*
* 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_ffc_params_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[])
{
const OSSL_PARAM *prm;
const OSSL_PARAM *param_p, *param_q, *param_g;
BIGNUM *p = NULL, *q = NULL, *g = NULL, *j = NULL;
int i;
if (ffc == NULL)
return 0;
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
if (prm != NULL) {
/*
* In a no-dh build we just go straight to err because we have no
* support for this.
*/
#ifndef OPENSSL_NO_DH
const DH_NAMED_GROUP *group = NULL;
if (prm->data_type != OSSL_PARAM_UTF8_STRING
|| prm->data == NULL
|| (group = ossl_ffc_name_to_dh_named_group(prm->data)) == NULL
|| !ossl_ffc_named_group_set(ffc, group))
#endif
goto err;
}
param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P);
param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G);
param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q);
if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
|| (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q))
|| (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g)))
goto err;
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX);
if (prm != NULL) {
if (!OSSL_PARAM_get_int(prm, &i))
goto err;
ffc->gindex = i;
}
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER);
if (prm != NULL) {
if (!OSSL_PARAM_get_int(prm, &i))
goto err;
ffc->pcounter = i;
}
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_COFACTOR);
if (prm != NULL && !OSSL_PARAM_get_BN(prm, &j))
goto err;
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H);
if (prm != NULL) {
if (!OSSL_PARAM_get_int(prm, &i))
goto err;
ffc->h = i;
}
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED);
if (prm != NULL) {
if (prm->data_type != OSSL_PARAM_OCTET_STRING)
goto err;
if (!ossl_ffc_params_set_seed(ffc, prm->data, prm->data_size))
goto err;
}
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_VALIDATE_PQ);
if (prm != NULL) {
if (!OSSL_PARAM_get_int(prm, &i))
goto err;
ossl_ffc_params_enable_flags(ffc, FFC_PARAM_FLAG_VALIDATE_PQ, i);
}
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_VALIDATE_G);
if (prm != NULL) {
if (!OSSL_PARAM_get_int(prm, &i))
goto err;
ossl_ffc_params_enable_flags(ffc, FFC_PARAM_FLAG_VALIDATE_G, i);
}
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY);
if (prm != NULL) {
if (!OSSL_PARAM_get_int(prm, &i))
goto err;
ossl_ffc_params_enable_flags(ffc, FFC_PARAM_FLAG_VALIDATE_LEGACY, i);
}
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST);
if (prm != NULL) {
const OSSL_PARAM *p1;
const char *props = NULL;
if (prm->data_type != OSSL_PARAM_UTF8_STRING)
goto err;
p1 = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS);
if (p1 != NULL) {
if (p1->data_type != OSSL_PARAM_UTF8_STRING)
goto err;
+ props = p1->data;
}
if (!ossl_ffc_set_digest(ffc, prm->data, props))
goto err;
}
ossl_ffc_params_set0_pqg(ffc, p, q, g);
ossl_ffc_params_set0_j(ffc, j);
return 1;
err:
BN_free(j);
BN_free(p);
BN_free(q);
BN_free(g);
return 0;
}
diff --git a/crypto/ffc/ffc_params.c b/crypto/ffc/ffc_params.c
index fb558f8221f6..3536efd1ad85 100644
--- a/crypto/ffc/ffc_params.c
+++ b/crypto/ffc/ffc_params.c
@@ -1,322 +1,324 @@
/*
- * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <string.h> /* memset */
#include <openssl/core_names.h>
#include "internal/ffc.h"
#include "internal/param_build_set.h"
#include "internal/nelem.h"
#ifndef FIPS_MODULE
# include <openssl/asn1.h> /* ossl_ffc_params_print */
#endif
void ossl_ffc_params_init(FFC_PARAMS *params)
{
memset(params, 0, sizeof(*params));
params->pcounter = -1;
params->gindex = FFC_UNVERIFIABLE_GINDEX;
params->flags = FFC_PARAM_FLAG_VALIDATE_PQG;
}
void ossl_ffc_params_cleanup(FFC_PARAMS *params)
{
BN_free(params->p);
BN_free(params->q);
BN_free(params->g);
BN_free(params->j);
OPENSSL_free(params->seed);
ossl_ffc_params_init(params);
}
void ossl_ffc_params_set0_pqg(FFC_PARAMS *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
{
if (p != NULL && p != d->p) {
BN_free(d->p);
d->p = p;
}
if (q != NULL && q != d->q) {
BN_free(d->q);
d->q = q;
}
if (g != NULL && g != d->g) {
BN_free(d->g);
d->g = g;
}
}
void ossl_ffc_params_get0_pqg(const FFC_PARAMS *d, const BIGNUM **p,
const BIGNUM **q, const BIGNUM **g)
{
if (p != NULL)
*p = d->p;
if (q != NULL)
*q = d->q;
if (g != NULL)
*g = d->g;
}
/* j is the 'cofactor' that is optionally output for ASN1. */
void ossl_ffc_params_set0_j(FFC_PARAMS *d, BIGNUM *j)
{
BN_free(d->j);
d->j = NULL;
if (j != NULL)
d->j = j;
}
int ossl_ffc_params_set_seed(FFC_PARAMS *params,
const unsigned char *seed, size_t seedlen)
{
if (params == NULL)
return 0;
if (params->seed != NULL) {
if (params->seed == seed)
return 1;
OPENSSL_free(params->seed);
}
if (seed != NULL && seedlen > 0) {
params->seed = OPENSSL_memdup(seed, seedlen);
if (params->seed == NULL)
return 0;
params->seedlen = seedlen;
} else {
params->seed = NULL;
params->seedlen = 0;
}
return 1;
}
void ossl_ffc_params_set_gindex(FFC_PARAMS *params, int index)
{
params->gindex = index;
}
void ossl_ffc_params_set_pcounter(FFC_PARAMS *params, int index)
{
params->pcounter = index;
}
void ossl_ffc_params_set_h(FFC_PARAMS *params, int index)
{
params->h = index;
}
void ossl_ffc_params_set_flags(FFC_PARAMS *params, unsigned int flags)
{
params->flags = flags;
}
void ossl_ffc_params_enable_flags(FFC_PARAMS *params, unsigned int flags,
int enable)
{
if (enable)
params->flags |= flags;
else
params->flags &= ~flags;
}
int ossl_ffc_set_digest(FFC_PARAMS *params, const char *alg, const char *props)
{
params->mdname = alg;
params->mdprops = props;
return 1;
}
int ossl_ffc_params_set_validate_params(FFC_PARAMS *params,
const unsigned char *seed,
size_t seedlen, int counter)
{
if (!ossl_ffc_params_set_seed(params, seed, seedlen))
return 0;
params->pcounter = counter;
return 1;
}
void ossl_ffc_params_get_validate_params(const FFC_PARAMS *params,
unsigned char **seed, size_t *seedlen,
int *pcounter)
{
if (seed != NULL)
*seed = params->seed;
if (seedlen != NULL)
*seedlen = params->seedlen;
if (pcounter != NULL)
*pcounter = params->pcounter;
}
static int ffc_bn_cpy(BIGNUM **dst, const BIGNUM *src)
{
BIGNUM *a;
/*
* If source is read only just copy the pointer, so
* we don't have to reallocate it.
*/
if (src == NULL)
a = NULL;
else if (BN_get_flags(src, BN_FLG_STATIC_DATA)
&& !BN_get_flags(src, BN_FLG_MALLOCED))
a = (BIGNUM *)src;
else if ((a = BN_dup(src)) == NULL)
return 0;
BN_clear_free(*dst);
*dst = a;
return 1;
}
int ossl_ffc_params_copy(FFC_PARAMS *dst, const FFC_PARAMS *src)
{
if (!ffc_bn_cpy(&dst->p, src->p)
|| !ffc_bn_cpy(&dst->g, src->g)
|| !ffc_bn_cpy(&dst->q, src->q)
|| !ffc_bn_cpy(&dst->j, src->j))
return 0;
+ dst->mdname = src->mdname;
+ dst->mdprops = src->mdprops;
OPENSSL_free(dst->seed);
dst->seedlen = src->seedlen;
if (src->seed != NULL) {
dst->seed = OPENSSL_memdup(src->seed, src->seedlen);
if (dst->seed == NULL)
return 0;
} else {
dst->seed = NULL;
}
dst->nid = src->nid;
dst->pcounter = src->pcounter;
dst->h = src->h;
dst->gindex = src->gindex;
dst->flags = src->flags;
dst->keylength = src->keylength;
return 1;
}
int ossl_ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q)
{
return BN_cmp(a->p, b->p) == 0
&& BN_cmp(a->g, b->g) == 0
&& (ignore_q || BN_cmp(a->q, b->q) == 0); /* Note: q may be NULL */
}
int ossl_ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *bld,
OSSL_PARAM params[])
{
int test_flags;
if (ffc == NULL)
return 0;
if (ffc->p != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_P, ffc->p))
return 0;
if (ffc->q != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_Q, ffc->q))
return 0;
if (ffc->g != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_G, ffc->g))
return 0;
if (ffc->j != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_COFACTOR,
ffc->j))
return 0;
if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_GINDEX,
ffc->gindex))
return 0;
if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_PCOUNTER,
ffc->pcounter))
return 0;
if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_H, ffc->h))
return 0;
if (ffc->seed != NULL
&& !ossl_param_build_set_octet_string(bld, params,
OSSL_PKEY_PARAM_FFC_SEED,
ffc->seed, ffc->seedlen))
return 0;
if (ffc->nid != NID_undef) {
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
|| !ossl_param_build_set_utf8_string(bld, params,
OSSL_PKEY_PARAM_GROUP_NAME,
name))
return 0;
}
test_flags = ((ffc->flags & FFC_PARAM_FLAG_VALIDATE_PQ) != 0);
if (!ossl_param_build_set_int(bld, params,
OSSL_PKEY_PARAM_FFC_VALIDATE_PQ, test_flags))
return 0;
test_flags = ((ffc->flags & FFC_PARAM_FLAG_VALIDATE_G) != 0);
if (!ossl_param_build_set_int(bld, params,
OSSL_PKEY_PARAM_FFC_VALIDATE_G, test_flags))
return 0;
test_flags = ((ffc->flags & FFC_PARAM_FLAG_VALIDATE_LEGACY) != 0);
if (!ossl_param_build_set_int(bld, params,
OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY,
test_flags))
return 0;
if (ffc->mdname != NULL
&& !ossl_param_build_set_utf8_string(bld, params,
OSSL_PKEY_PARAM_FFC_DIGEST,
ffc->mdname))
return 0;
if (ffc->mdprops != NULL
&& !ossl_param_build_set_utf8_string(bld, params,
OSSL_PKEY_PARAM_FFC_DIGEST_PROPS,
ffc->mdprops))
return 0;
return 1;
}
#ifndef FIPS_MODULE
int ossl_ffc_params_print(BIO *bp, const FFC_PARAMS *ffc, int indent)
{
if (!ASN1_bn_print(bp, "prime P:", ffc->p, NULL, indent))
goto err;
if (!ASN1_bn_print(bp, "generator G:", ffc->g, NULL, indent))
goto err;
if (ffc->q != NULL
&& !ASN1_bn_print(bp, "subgroup order Q:", ffc->q, NULL, indent))
goto err;
if (ffc->j != NULL
&& !ASN1_bn_print(bp, "subgroup factor:", ffc->j, NULL, indent))
goto err;
if (ffc->seed != NULL) {
size_t i;
if (!BIO_indent(bp, indent, 128)
|| BIO_puts(bp, "seed:") <= 0)
goto err;
for (i = 0; i < ffc->seedlen; i++) {
if ((i % 15) == 0) {
if (BIO_puts(bp, "\n") <= 0
|| !BIO_indent(bp, indent + 4, 128))
goto err;
}
if (BIO_printf(bp, "%02x%s", ffc->seed[i],
((i + 1) == ffc->seedlen) ? "" : ":") <= 0)
goto err;
}
if (BIO_write(bp, "\n", 1) <= 0)
return 0;
}
if (ffc->pcounter != -1) {
if (!BIO_indent(bp, indent, 128)
|| BIO_printf(bp, "counter: %d\n", ffc->pcounter) <= 0)
goto err;
}
return 1;
err:
return 0;
}
#endif /* FIPS_MODULE */
diff --git a/crypto/http/http_client.c b/crypto/http/http_client.c
index 0d62f1c7bf16..ee41c03103e5 100644
--- a/crypto/http/http_client.c
+++ b/crypto/http/http_client.c
@@ -1,1422 +1,1427 @@
/*
- * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 port) must be given if and only if plain HTTP proxy is used.
*/
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 */
if (path == NULL)
path = "/";
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);
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);
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
/* 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;
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;
+ 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 */))
+ 0 /* no keep_alive */)) {
OSSL_HTTP_REQ_CTX_free(rctx);
- else
+ 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/http/http_lib.c b/crypto/http/http_lib.c
index bd9c096b989c..ec24e0dc488e 100644
--- a/crypto/http/http_lib.c
+++ b/crypto/http/http_lib.c
@@ -1,286 +1,285 @@
/*
- * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-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> /* for sscanf() */
#include <string.h>
#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() */
static void init_pstring(char **pstr)
{
if (pstr != NULL) {
*pstr = NULL;
}
}
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_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) || 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;
if (!ossl_assert(server != NULL))
return 0;
sl = strlen(server);
/*
* 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 = getenv("no_proxy");
+ no_proxy = ossl_safe_getenv("no_proxy");
if (no_proxy == NULL)
- no_proxy = getenv(OPENSSL_NO_PROXY);
+ 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 = 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 = getenv(use_ssl ? "https_proxy" : "http_proxy");
+ proxy = ossl_safe_getenv(use_ssl ? "https_proxy" : "http_proxy");
if (proxy == NULL)
- proxy = getenv(use_ssl ? OPENSSL_HTTP_PROXY :
- OPENSSL_HTTPS_PROXY);
+ proxy = ossl_safe_getenv(use_ssl ? OPENSSL_HTTP_PROXY : OPENSSL_HTTPS_PROXY);
if (proxy == NULL || *proxy == '\0' || !use_proxy(no_proxy, server))
return NULL;
return proxy;
}
diff --git a/crypto/modes/asm/aes-gcm-armv8_64.pl b/crypto/modes/asm/aes-gcm-armv8_64.pl
index 3b9d5b651193..302b6f5a8ec8 100755
--- a/crypto/modes/asm/aes-gcm-armv8_64.pl
+++ b/crypto/modes/asm/aes-gcm-armv8_64.pl
@@ -1,5722 +1,6097 @@
#! /usr/bin/env perl
-# Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+# 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
#
#========================================================================
# Written by Fangming Fang <fangming.fang@arm.com> for the OpenSSL project,
# derived from https://github.com/ARM-software/AArch64cryptolib, original
# author Samuel Lee <Samuel.Lee@arm.com>. 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/.
#========================================================================
#
# Approach - assume we don't want to reload constants, so reserve ~half of vector register file for constants
#
# main loop to act on 4 16B blocks per iteration, and then do modulo of the accumulated intermediate hashes from the 4 blocks
#
# ____________________________________________________
# | |
# | PRE |
# |____________________________________________________|
# | | | |
# | CTR block 4k+8 | AES block 4k+4 | GHASH block 4k+0 |
# |________________|________________|__________________|
# | | | |
# | CTR block 4k+9 | AES block 4k+5 | GHASH block 4k+1 |
# |________________|________________|__________________|
# | | | |
# | CTR block 4k+10| AES block 4k+6 | GHASH block 4k+2 |
# |________________|________________|__________________|
# | | | |
# | CTR block 4k+11| AES block 4k+7 | GHASH block 4k+3 |
# |________________|____(mostly)____|__________________|
# | |
# | MODULO |
# |____________________________________________________|
#
# PRE:
# Ensure previous generated intermediate hash is aligned and merged with result for GHASH 4k+0
# EXT low_acc, low_acc, low_acc, #8
# EOR res_curr (4k+0), res_curr (4k+0), low_acc
#
# CTR block:
# Increment and byte reverse counter in scalar registers and transfer to SIMD registers
# REV ctr32, rev_ctr32
# ORR ctr64, constctr96_top32, ctr32, LSL #32
# INS ctr_next.d[0], constctr96_bottom64 // Keeping this in scalar registers to free up space in SIMD RF
# INS ctr_next.d[1], ctr64X
# ADD rev_ctr32, #1
#
# AES block:
# Do AES encryption/decryption on CTR block X and EOR it with input block X. Take 256 bytes key below for example.
# Doing small trick here of loading input in scalar registers, EORing with last key and then transferring
# Given we are very constrained in our ASIMD registers this is quite important
#
# Encrypt:
# LDR input_low, [ input_ptr ], #8
# LDR input_high, [ input_ptr ], #8
# EOR input_low, k14_low
# EOR input_high, k14_high
# INS res_curr.d[0], input_low
# INS res_curr.d[1], input_high
# AESE ctr_curr, k0; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k1; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k2; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k3; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k4; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k5; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k6; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k7; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k8; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k9; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k10; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k11; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k12; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k13
# EOR res_curr, res_curr, ctr_curr
# ST1 { res_curr.16b }, [ output_ptr ], #16
#
# Decrypt:
# AESE ctr_curr, k0; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k1; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k2; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k3; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k4; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k5; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k6; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k7; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k8; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k9; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k10; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k11; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k12; AESMC ctr_curr, ctr_curr
# AESE ctr_curr, k13
# LDR res_curr, [ input_ptr ], #16
# EOR res_curr, res_curr, ctr_curr
# MOV output_low, res_curr.d[0]
# MOV output_high, res_curr.d[1]
# EOR output_low, k14_low
# EOR output_high, k14_high
# STP output_low, output_high, [ output_ptr ], #16
#
# GHASH block X:
# do 128b karatsuba polynomial multiplication on block
# We only have 64b->128b polynomial multipliers, naively that means we need to do 4 64b multiplies to generate a 128b
#
# multiplication:
# Pmull(A,B) == (Pmull(Ah,Bh)<<128 | Pmull(Al,Bl)) ^ (Pmull(Ah,Bl) ^ Pmull(Al,Bh))<<64
#
# The idea behind Karatsuba multiplication is that we can do just 3 64b multiplies:
# Pmull(A,B) == (Pmull(Ah,Bh)<<128 | Pmull(Al,Bl)) ^ (Pmull(Ah^Al,Bh^Bl) ^ Pmull(Ah,Bh) ^ Pmull(Al,Bl))<<64
#
# There is some complication here because the bit order of GHASH's PMULL is reversed compared to elsewhere, so we are
# multiplying with "twisted" powers of H
#
# Note: We can PMULL directly into the acc_x in first GHASH of the loop
# Note: For scheduling big cores we want to split the processing to happen over two loop iterations - otherwise the critical
# path latency dominates the performance
#
# This has a knock on effect on register pressure, so we have to be a bit more clever with our temporary registers
# than indicated here
# REV64 res_curr, res_curr
# INS t_m.d[0], res_curr.d[1]
# EOR t_m.8B, t_m.8B, res_curr.8B
# PMULL2 t_h, res_curr, HX
# PMULL t_l, res_curr, HX
# PMULL t_m, t_m, HX_k
# EOR acc_h, acc_h, t_h
# EOR acc_l, acc_l, t_l
# EOR acc_m, acc_m, t_m
#
# MODULO: take the partial accumulators (~representing sum of 256b multiplication results), from GHASH and do modulo reduction on them
# There is some complication here because the bit order of GHASH's PMULL is reversed compared to elsewhere, so we are doing modulo
# with a reversed constant
# EOR acc_m, acc_m, acc_h
# EOR acc_m, acc_m, acc_l // Finish off karatsuba processing
# PMULL t_mod, acc_h, mod_constant
# EXT acc_h, acc_h, acc_h, #8
# EOR acc_m, acc_m, acc_h
# EOR acc_m, acc_m, t_mod
# PMULL acc_h, acc_m, mod_constant
# EXT acc_m, acc_m, acc_m, #8
# EOR acc_l, acc_l, acc_h
# EOR acc_l, acc_l, acc_m
$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
$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";
*STDOUT=*OUT;
$input_ptr="x0"; #argument block
$bit_length="x1";
$output_ptr="x2";
$current_tag="x3";
$counter="x16";
$cc="x8";
{
my ($end_input_ptr,$main_end_input_ptr,$input_l0,$input_h0)=map("x$_",(4..7));
my ($input_l1,$input_h1,$input_l2,$input_h2,$input_l3,$input_h3)=map("x$_",(19..24));
my ($output_l1,$output_h1,$output_l2,$output_h2,$output_l3,$output_h3)=map("x$_",(19..24));
my ($output_l0,$output_h0)=map("x$_",(6..7));
my $ctr32w="w9";
my ($ctr32x,$ctr96_b64x,$ctr96_t32x,$rctr32x,$rk10_l,$rk10_h,$len)=map("x$_",(9..15));
my ($ctr96_t32w,$rctr32w)=map("w$_",(11..12));
my ($ctr0b,$ctr1b,$ctr2b,$ctr3b,$res0b,$res1b,$res2b,$res3b)=map("v$_.16b",(0..7));
my ($ctr0,$ctr1,$ctr2,$ctr3,$res0,$res1,$res2,$res3)=map("v$_",(0..7));
my ($ctr0d,$ctr1d,$ctr2d,$ctr3d,$res0d,$res1d,$res2d,$res3d)=map("d$_",(0..7));
my ($res0q,$res1q,$res2q,$res3q)=map("q$_",(4..7));
my ($acc_hb,$acc_mb,$acc_lb)=map("v$_.16b",(9..11));
my ($acc_h,$acc_m,$acc_l)=map("v$_",(9..11));
my ($acc_hd,$acc_md,$acc_ld)=map("d$_",(9..11));
my ($h1,$h2,$h3,$h4,$h12k,$h34k)=map("v$_",(12..17));
my ($h1q,$h2q,$h3q,$h4q)=map("q$_",(12..15));
my ($h1b,$h2b,$h3b,$h4b)=map("v$_.16b",(12..15));
my $t0="v8";
my $t0d="d8";
my ($t1,$t2,$t3)=map("v$_",(28..30));
my ($t1d,$t2d,$t3d)=map("d$_",(28..30));
my $t4="v8";
my $t4d="d8";
my $t5="v28";
my $t5d="d28";
my $t6="v31";
my $t6d="d31";
my $t7="v4";
my $t7d="d4";
my $t8="v29";
my $t8d="d29";
my $t9="v30";
my $t9d="d30";
my ($ctr_t0,$ctr_t1,$ctr_t2,$ctr_t3)=map("v$_",(4..7));
my ($ctr_t0d,$ctr_t1d,$ctr_t2d,$ctr_t3d)=map("d$_",(4..7));
my ($ctr_t0b,$ctr_t1b,$ctr_t2b,$ctr_t3b)=map("v$_.16b",(4..7));
my $mod_constantd="d8";
my $mod_constant="v8";
my $mod_t="v31";
my ($rk0,$rk1,$rk2,$rk3,$rk4,$rk5,$rk6,$rk7,$rk8,$rk9)=map("v$_.16b",(18..27));
+my ($rk0s,$rk1s,$rk2s,$rk3s,$rk4s,$rk5s,$rk6s,$rk7s,$rk8s,$rk9s)=map("v$_.4s",(18..27));
my ($rk0q,$rk1q,$rk2q,$rk3q,$rk4q,$rk5q,$rk6q,$rk7q,$rk8q,$rk9q)=map("q$_",(18..27));
my $rk2q1="v20.1q";
my $rk3q1="v21.1q";
my $rk4v="v22";
my $rk4d="d22";
$code=<<___;
#include "arm_arch.h"
#if __ARM_MAX_ARCH__>=8
___
$code.=".arch armv8-a+crypto\n.text\n" if ($flavour =~ /64/);
$code.=<<___ if ($flavour !~ /64/);
.fpu neon
#ifdef __thumb2__
.syntax unified
.thumb
# define INST(a,b,c,d) $_byte c,0xef,a,b
#else
.code 32
# define INST(a,b,c,d) $_byte a,b,c,0xf2
#endif
.text
___
#########################################################################################
# size_t aes_gcm_enc_128_kernel(const unsigned char *in,
# size_t len,
# unsigned char *out,
# const void *key,
# unsigned char ivec[16],
# u64 *Xi);
#
$code.=<<___;
.global aes_gcm_enc_128_kernel
.type aes_gcm_enc_128_kernel,%function
.align 4
aes_gcm_enc_128_kernel:
cbz x1, .L128_enc_ret
stp x19, x20, [sp, #-112]!
mov x16, x4
mov x8, x5
stp x21, x22, [sp, #16]
stp x23, x24, [sp, #32]
stp d8, d9, [sp, #48]
stp d10, d11, [sp, #64]
stp d12, d13, [sp, #80]
stp d14, d15, [sp, #96]
ldp $ctr96_b64x, $ctr96_t32x, [$counter] @ ctr96_b64, ctr96_t32
+#ifdef __AARCH64EB__
+ rev $ctr96_b64x, $ctr96_b64x
+ rev $ctr96_t32x, $ctr96_t32x
+#endif
ldp $rk10_l, $rk10_h, [$cc, #160] @ load rk10
-
+#ifdef __AARCH64EB__
+ ror $rk10_l, $rk10_l, #32
+ ror $rk10_h, $rk10_h, #32
+#endif
ld1 {$acc_lb}, [$current_tag]
ext $acc_lb, $acc_lb, $acc_lb, #8
rev64 $acc_lb, $acc_lb
lsr $main_end_input_ptr, $bit_length, #3 @ byte_len
mov $len, $main_end_input_ptr
- ldr $rk9q, [$cc, #144] @ load rk9
+ ld1 {$rk0s}, [$cc], #16 @ load rk0
add $end_input_ptr, $input_ptr, $bit_length, lsr #3 @ end_input_ptr
sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
lsr $rctr32x, $ctr96_t32x, #32
ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+#ifndef __AARCH64EB__
ext $h4b, $h4b, $h4b, #8
-
+#endif
fmov $ctr1d, $ctr96_b64x @ CTR block 1
rev $rctr32w, $rctr32w @ rev_ctr32
add $rctr32w, $rctr32w, #1 @ increment rev_ctr32
orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
- ldr $rk0q, [$cc, #0] @ load rk0
+ ld1 {$rk1s}, [$cc], #16 @ load rk1
rev $ctr32w, $rctr32w @ CTR block 1
add $rctr32w, $rctr32w, #1 @ CTR block 1
fmov $ctr3d, $ctr96_b64x @ CTR block 3
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 1
ld1 { $ctr0b}, [$counter] @ special case vector load initial counter so we can start first AES block as quickly as possible
fmov $ctr1.d[1], $ctr32x @ CTR block 1
rev $ctr32w, $rctr32w @ CTR block 2
fmov $ctr2d, $ctr96_b64x @ CTR block 2
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 2
add $rctr32w, $rctr32w, #1 @ CTR block 2
fmov $ctr2.d[1], $ctr32x @ CTR block 2
rev $ctr32w, $rctr32w @ CTR block 3
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 3
- ldr $rk1q, [$cc, #16] @ load rk1
+ ld1 {$rk2s}, [$cc], #16 @ load rk2
add $rctr32w, $rctr32w, #1 @ CTR block 3
fmov $ctr3.d[1], $ctr32x @ CTR block 3
ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+#ifndef __AARCH64EB__
ext $h3b, $h3b, $h3b, #8
-
+#endif
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
- ldr $rk2q, [$cc, #32] @ load rk2
+ ld1 {$rk3s}, [$cc], #16 @ load rk3
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+#ifndef __AARCH64EB__
ext $h1b, $h1b, $h1b, #8
+#endif
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
- ldr $rk8q, [$cc, #128] @ load rk8
+ ld1 {$rk4s}, [$cc], #16 @ load rk4
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
- ldr $rk3q, [$cc, #48] @ load rk3
+ ld1 {$rk5s}, [$cc], #16 @ load rk5
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
trn2 $h34k.2d, $h3.2d, $h4.2d @ h4l | h3l
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
- ldr $rk6q, [$cc, #96] @ load rk6
+ ld1 {$rk6s}, [$cc], #16 @ load rk6
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
- ldr $rk7q, [$cc, #112] @ load rk7
+ ld1 {$rk7s}, [$cc], #16 @ load rk7
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
trn1 $acc_h.2d, $h3.2d, $h4.2d @ h4h | h3h
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
- ldr $rk5q, [$cc, #80] @ load rk5
+ ld1 {$rk8s}, [$cc], #16 @ load rk8
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+#ifndef __AARCH64EB__
ext $h2b, $h2b, $h2b, #8
+#endif
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
eor $h34k.16b, $h34k.16b, $acc_h.16b @ h4k | h3k
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 3
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 3
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 3
- ldr $rk4q, [$cc, #64] @ load rk4
+ ld1 {$rk9s}, [$cc], #16 @ load rk9
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 3
and $main_end_input_ptr, $main_end_input_ptr, #0xffffffffffffffc0 @ number of bytes to be processed in main loop (at least 1 byte must be handled by tail)
trn2 $h12k.2d, $h1.2d, $h2.2d @ h2l | h1l
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 4
add $main_end_input_ptr, $main_end_input_ptr, $input_ptr
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 4
cmp $input_ptr, $main_end_input_ptr @ check if we have <= 4 blocks
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 4
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 5
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 5
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 5
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 6
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 4
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 6
trn1 $t0.2d, $h1.2d, $h2.2d @ h2h | h1h
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 6
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 5
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 7
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 7
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 6
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 7
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 8
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 7
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 8
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 8
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 8
aese $ctr2b, $rk9 @ AES block 2 - round 9
aese $ctr0b, $rk9 @ AES block 0 - round 9
eor $h12k.16b, $h12k.16b, $t0.16b @ h2k | h1k
aese $ctr1b, $rk9 @ AES block 1 - round 9
aese $ctr3b, $rk9 @ AES block 3 - round 9
b.ge .L128_enc_tail @ handle tail
ldp $input_l0, $input_h0, [$input_ptr, #0] @ AES block 0 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 2 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l2, $input_l2
+ rev $input_h2, $input_h2
+#endif
ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 1 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l1, $input_l1
+ rev $input_h1, $input_h1
+#endif
ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 3 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l3, $input_l3
+ rev $input_h3, $input_h3
+#endif
eor $input_l0, $input_l0, $rk10_l @ AES block 0 - round 10 low
eor $input_h0, $input_h0, $rk10_h @ AES block 0 - round 10 high
eor $input_l2, $input_l2, $rk10_l @ AES block 2 - round 10 low
fmov $ctr_t0d, $input_l0 @ AES block 0 - mov low
eor $input_l1, $input_l1, $rk10_l @ AES block 1 - round 10 low
eor $input_h2, $input_h2, $rk10_h @ AES block 2 - round 10 high
fmov $ctr_t0.d[1], $input_h0 @ AES block 0 - mov high
fmov $ctr_t1d, $input_l1 @ AES block 1 - mov low
eor $input_h1, $input_h1, $rk10_h @ AES block 1 - round 10 high
eor $input_l3, $input_l3, $rk10_l @ AES block 3 - round 10 low
fmov $ctr_t1.d[1], $input_h1 @ AES block 1 - mov high
fmov $ctr_t2d, $input_l2 @ AES block 2 - mov low
eor $input_h3, $input_h3, $rk10_h @ AES block 3 - round 10 high
rev $ctr32w, $rctr32w @ CTR block 4
fmov $ctr_t2.d[1], $input_h2 @ AES block 2 - mov high
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4
eor $res0b, $ctr_t0b, $ctr0b @ AES block 0 - result
fmov $ctr0d, $ctr96_b64x @ CTR block 4
add $rctr32w, $rctr32w, #1 @ CTR block 4
fmov $ctr0.d[1], $ctr32x @ CTR block 4
rev $ctr32w, $rctr32w @ CTR block 5
eor $res1b, $ctr_t1b, $ctr1b @ AES block 1 - result
fmov $ctr1d, $ctr96_b64x @ CTR block 5
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 5
add $rctr32w, $rctr32w, #1 @ CTR block 5
add $input_ptr, $input_ptr, #64 @ AES input_ptr update
fmov $ctr1.d[1], $ctr32x @ CTR block 5
fmov $ctr_t3d, $input_l3 @ AES block 3 - mov low
rev $ctr32w, $rctr32w @ CTR block 6
st1 { $res0b}, [$output_ptr], #16 @ AES block 0 - store result
fmov $ctr_t3.d[1], $input_h3 @ AES block 3 - mov high
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 6
add $rctr32w, $rctr32w, #1 @ CTR block 6
eor $res2b, $ctr_t2b, $ctr2b @ AES block 2 - result
st1 { $res1b}, [$output_ptr], #16 @ AES block 1 - store result
fmov $ctr2d, $ctr96_b64x @ CTR block 6
cmp $input_ptr, $main_end_input_ptr @ check if we have <= 8 blocks
fmov $ctr2.d[1], $ctr32x @ CTR block 6
rev $ctr32w, $rctr32w @ CTR block 7
st1 { $res2b}, [$output_ptr], #16 @ AES block 2 - store result
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 7
eor $res3b, $ctr_t3b, $ctr3b @ AES block 3 - result
st1 { $res3b}, [$output_ptr], #16 @ AES block 3 - store result
b.ge .L128_enc_prepretail @ do prepretail
.L128_enc_main_loop: @ main loop start
ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 4k+3 - load plaintext
+#ifdef __AARCH64EB__
+ rev $input_l3, $input_l3
+ rev $input_h3, $input_h3
+#endif
rev64 $res0b, $res0b @ GHASH block 4k (only t0 is free)
rev64 $res2b, $res2b @ GHASH block 4k+2 (t0, t1, and t2 free)
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
fmov $ctr3d, $ctr96_b64x @ CTR block 4k+3
ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
rev64 $res1b, $res1b @ GHASH block 4k+1 (t0 and t1 free)
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
add $rctr32w, $rctr32w, #1 @ CTR block 4k+3
fmov $ctr3.d[1], $ctr32x @ CTR block 4k+3
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
eor $res0b, $res0b, $acc_lb @ PRE 1
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
eor $input_h3, $input_h3, $rk10_h @ AES block 4k+3 - round 10 high
pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
ldp $input_l0, $input_h0, [$input_ptr, #0] @ AES block 4k+4 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
rev $ctr32w, $rctr32w @ CTR block 4k+8
eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
mov $t0d, $res0.d[1] @ GHASH block 4k - mid
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+8
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
add $rctr32w, $rctr32w, #1 @ CTR block 4k+8
mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
rev64 $res3b, $res3b @ GHASH block 4k+3 (t0, t1, t2 and t3 free)
pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
eor $input_h0, $input_h0, $rk10_h @ AES block 4k+4 - round 10 high
eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
eor $input_l0, $input_l0, $rk10_l @ AES block 4k+4 - round 10 low
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
movi $mod_constant.8b, #0xc2
pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 4k+5 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l1, $input_l1
+ rev $input_h1, $input_h1
+#endif
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 4k+6 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l2, $input_l2
+ rev $input_h2, $input_h2
+#endif
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
eor $input_l1, $input_l1, $rk10_l @ AES block 4k+5 - round 10 low
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
eor $input_l3, $input_l3, $rk10_l @ AES block 4k+3 - round 10 low
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
fmov $ctr_t0d, $input_l0 @ AES block 4k+4 - mov low
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
fmov $ctr_t0.d[1], $input_h0 @ AES block 4k+4 - mov high
add $input_ptr, $input_ptr, #64 @ AES input_ptr update
fmov $ctr_t3d, $input_l3 @ AES block 4k+3 - mov low
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
fmov $ctr_t1d, $input_l1 @ AES block 4k+5 - mov low
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
eor $input_h1, $input_h1, $rk10_h @ AES block 4k+5 - round 10 high
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
fmov $ctr_t1.d[1], $input_h1 @ AES block 4k+5 - mov high
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
fmov $ctr_t3.d[1], $input_h3 @ AES block 4k+3 - mov high
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
cmp $input_ptr, $main_end_input_ptr @ LOOP CONTROL
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
aese $ctr0b, $rk9 @ AES block 4k+4 - round 9
eor $input_l2, $input_l2, $rk10_l @ AES block 4k+6 - round 10 low
eor $input_h2, $input_h2, $rk10_h @ AES block 4k+6 - round 10 high
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
fmov $ctr_t2d, $input_l2 @ AES block 4k+6 - mov low
aese $ctr1b, $rk9 @ AES block 4k+5 - round 9
fmov $ctr_t2.d[1], $input_h2 @ AES block 4k+6 - mov high
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
eor $res0b, $ctr_t0b, $ctr0b @ AES block 4k+4 - result
fmov $ctr0d, $ctr96_b64x @ CTR block 4k+8
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
fmov $ctr0.d[1], $ctr32x @ CTR block 4k+8
rev $ctr32w, $rctr32w @ CTR block 4k+9
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
eor $res1b, $ctr_t1b, $ctr1b @ AES block 4k+5 - result
add $rctr32w, $rctr32w, #1 @ CTR block 4k+9
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+9
fmov $ctr1d, $ctr96_b64x @ CTR block 4k+9
pmull $acc_h.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
fmov $ctr1.d[1], $ctr32x @ CTR block 4k+9
rev $ctr32w, $rctr32w @ CTR block 4k+10
aese $ctr2b, $rk9 @ AES block 4k+6 - round 9
st1 { $res0b}, [$output_ptr], #16 @ AES block 4k+4 - store result
eor $res2b, $ctr_t2b, $ctr2b @ AES block 4k+6 - result
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+10
aese $ctr3b, $rk9 @ AES block 4k+7 - round 9
add $rctr32w, $rctr32w, #1 @ CTR block 4k+10
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
fmov $ctr2d, $ctr96_b64x @ CTR block 4k+10
eor $acc_lb, $acc_lb, $acc_hb @ MODULO - fold into low
st1 { $res1b}, [$output_ptr], #16 @ AES block 4k+5 - store result
fmov $ctr2.d[1], $ctr32x @ CTR block 4k+10
st1 { $res2b}, [$output_ptr], #16 @ AES block 4k+6 - store result
rev $ctr32w, $rctr32w @ CTR block 4k+11
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+11
eor $res3b, $ctr_t3b, $ctr3b @ AES block 4k+3 - result
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
st1 { $res3b}, [$output_ptr], #16 @ AES block 4k+3 - store result
b.lt .L128_enc_main_loop
.L128_enc_prepretail: @ PREPRETAIL
rev64 $res0b, $res0b @ GHASH block 4k (only t0 is free)
fmov $ctr3d, $ctr96_b64x @ CTR block 4k+3
rev64 $res1b, $res1b @ GHASH block 4k+1 (t0 and t1 free)
ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
add $rctr32w, $rctr32w, #1 @ CTR block 4k+3
fmov $ctr3.d[1], $ctr32x @ CTR block 4k+3
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
rev64 $res2b, $res2b @ GHASH block 4k+2 (t0, t1, and t2 free)
pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
rev64 $res3b, $res3b @ GHASH block 4k+3 (t0, t1, t2 and t3 free)
eor $res0b, $res0b, $acc_lb @ PRE 1
pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
mov $t0d, $res0.d[1] @ GHASH block 4k - mid
mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
movi $mod_constant.8b, #0xc2
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
pmull $t1.1q, $acc_h.1d, $mod_constant.1d
eor $acc_mb, $acc_mb, $acc_hb @ karatsuba tidy up
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
ext $acc_hb, $acc_hb, $acc_hb, #8
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
eor $acc_mb, $acc_mb, $acc_lb
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
eor $acc_mb, $acc_mb, $t1.16b
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
eor $acc_mb, $acc_mb, $acc_hb
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
pmull $t1.1q, $acc_m.1d, $mod_constant.1d
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
ext $acc_mb, $acc_mb, $acc_mb, #8
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
eor $acc_lb, $acc_lb, $t1.16b
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
aese $ctr3b, $rk9 @ AES block 4k+7 - round 9
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
aese $ctr0b, $rk9 @ AES block 4k+4 - round 9
aese $ctr1b, $rk9 @ AES block 4k+5 - round 9
eor $acc_lb, $acc_lb, $acc_mb
aese $ctr2b, $rk9 @ AES block 4k+6 - round 9
.L128_enc_tail: @ TAIL
sub $main_end_input_ptr, $end_input_ptr, $input_ptr @ main_end_input_ptr is number of bytes left to process
ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES block 4k+4 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
cmp $main_end_input_ptr, #48
ext $t0.16b, $acc_lb, $acc_lb, #8 @ prepare final partial tag
eor $input_l0, $input_l0, $rk10_l @ AES block 4k+4 - round 10 low
eor $input_h0, $input_h0, $rk10_h @ AES block 4k+4 - round 10 high
fmov $ctr_t0d, $input_l0 @ AES block 4k+4 - mov low
fmov $ctr_t0.d[1], $input_h0 @ AES block 4k+4 - mov high
eor $res1b, $ctr_t0b, $ctr0b @ AES block 4k+4 - result
b.gt .L128_enc_blocks_more_than_3
sub $rctr32w, $rctr32w, #1
movi $acc_l.8b, #0
mov $ctr3b, $ctr2b
cmp $main_end_input_ptr, #32
mov $ctr2b, $ctr1b
movi $acc_h.8b, #0
movi $acc_m.8b, #0
b.gt .L128_enc_blocks_more_than_2
mov $ctr3b, $ctr1b
cmp $main_end_input_ptr, #16
sub $rctr32w, $rctr32w, #1
b.gt .L128_enc_blocks_more_than_1
sub $rctr32w, $rctr32w, #1
b .L128_enc_blocks_less_than_1
.L128_enc_blocks_more_than_3: @ blocks left > 3
st1 { $res1b}, [$output_ptr], #16 @ AES final-3 block - store result
ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final-2 block - load input low & high
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
rev64 $res0b, $res1b @ GHASH final-3 block
eor $res0b, $res0b, $t0.16b @ feed in partial tag
eor $input_h0, $input_h0, $rk10_h @ AES final-2 block - round 10 high
eor $input_l0, $input_l0, $rk10_l @ AES final-2 block - round 10 low
fmov $res1d, $input_l0 @ AES final-2 block - mov low
movi $t0.8b, #0 @ suppress further partial tag feed in
fmov $res1.d[1], $input_h0 @ AES final-2 block - mov high
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH final-3 block - low
mov $rk4d, $res0.d[1] @ GHASH final-3 block - mid
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH final-3 block - high
mov $acc_md, $h34k.d[1] @ GHASH final-3 block - mid
eor $res1b, $res1b, $ctr1b @ AES final-2 block - result
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-3 block - mid
pmull $acc_m.1q, $rk4v.1d, $acc_m.1d @ GHASH final-3 block - mid
.L128_enc_blocks_more_than_2: @ blocks left > 2
st1 { $res1b}, [$output_ptr], #16 @ AES final-2 block - store result
rev64 $res0b, $res1b @ GHASH final-2 block
ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final-1 block - load input low & high
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
eor $res0b, $res0b, $t0.16b @ feed in partial tag
eor $input_l0, $input_l0, $rk10_l @ AES final-1 block - round 10 low
fmov $res1d, $input_l0 @ AES final-1 block - mov low
eor $input_h0, $input_h0, $rk10_h @ AES final-1 block - round 10 high
pmull2 $rk2q1, $res0.2d, $h3.2d @ GHASH final-2 block - high
fmov $res1.d[1], $input_h0 @ AES final-1 block - mov high
mov $rk4d, $res0.d[1] @ GHASH final-2 block - mid
pmull $rk3q1, $res0.1d, $h3.1d @ GHASH final-2 block - low
eor $acc_hb, $acc_hb, $rk2 @ GHASH final-2 block - high
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-2 block - mid
eor $res1b, $res1b, $ctr2b @ AES final-1 block - result
eor $acc_lb, $acc_lb, $rk3 @ GHASH final-2 block - low
pmull $rk4v.1q, $rk4v.1d, $h34k.1d @ GHASH final-2 block - mid
movi $t0.8b, #0 @ suppress further partial tag feed in
eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-2 block - mid
.L128_enc_blocks_more_than_1: @ blocks left > 1
st1 { $res1b}, [$output_ptr], #16 @ AES final-1 block - store result
rev64 $res0b, $res1b @ GHASH final-1 block
ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final block - load input low & high
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
eor $res0b, $res0b, $t0.16b @ feed in partial tag
eor $input_h0, $input_h0, $rk10_h @ AES final block - round 10 high
eor $input_l0, $input_l0, $rk10_l @ AES final block - round 10 low
fmov $res1d, $input_l0 @ AES final block - mov low
pmull2 $rk2q1, $res0.2d, $h2.2d @ GHASH final-1 block - high
fmov $res1.d[1], $input_h0 @ AES final block - mov high
mov $rk4d, $res0.d[1] @ GHASH final-1 block - mid
pmull $rk3q1, $res0.1d, $h2.1d @ GHASH final-1 block - low
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-1 block - mid
eor $res1b, $res1b, $ctr3b @ AES final block - result
ins $rk4v.d[1], $rk4v.d[0] @ GHASH final-1 block - mid
pmull2 $rk4v.1q, $rk4v.2d, $h12k.2d @ GHASH final-1 block - mid
eor $acc_lb, $acc_lb, $rk3 @ GHASH final-1 block - low
eor $acc_hb, $acc_hb, $rk2 @ GHASH final-1 block - high
eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-1 block - mid
movi $t0.8b, #0 @ suppress further partial tag feed in
.L128_enc_blocks_less_than_1: @ blocks left <= 1
and $bit_length, $bit_length, #127 @ bit_length %= 128
mvn $rk10_l, xzr @ rk10_l = 0xffffffffffffffff
mvn $rk10_h, xzr @ rk10_h = 0xffffffffffffffff
sub $bit_length, $bit_length, #128 @ bit_length -= 128
neg $bit_length, $bit_length @ bit_length = 128 - #bits in input (in range [1,128])
and $bit_length, $bit_length, #127 @ bit_length %= 128
lsr $rk10_h, $rk10_h, $bit_length @ rk10_h is mask for top 64b of last block
cmp $bit_length, #64
csel $input_l0, $rk10_l, $rk10_h, lt
csel $input_h0, $rk10_h, xzr, lt
fmov $ctr0d, $input_l0 @ ctr0b is mask for last block
fmov $ctr0.d[1], $input_h0
and $res1b, $res1b, $ctr0b @ possibly partial last block has zeroes in highest bits
rev64 $res0b, $res1b @ GHASH final block
eor $res0b, $res0b, $t0.16b @ feed in partial tag
mov $t0d, $res0.d[1] @ GHASH final block - mid
pmull $rk3q1, $res0.1d, $h1.1d @ GHASH final block - low
ld1 { $rk0}, [$output_ptr] @ load existing bytes where the possibly partial last block is to be stored
eor $t0.8b, $t0.8b, $res0.8b @ GHASH final block - mid
-
+#ifndef __AARCH64EB__
rev $ctr32w, $rctr32w
-
+#else
+ mov $ctr32w, $rctr32w
+#endif
pmull2 $rk2q1, $res0.2d, $h1.2d @ GHASH final block - high
pmull $t0.1q, $t0.1d, $h12k.1d @ GHASH final block - mid
eor $acc_lb, $acc_lb, $rk3 @ GHASH final block - low
eor $acc_hb, $acc_hb, $rk2 @ GHASH final block - high
eor $acc_mb, $acc_mb, $t0.16b @ GHASH final block - mid
movi $mod_constant.8b, #0xc2
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
pmull $acc_h.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
bif $res1b, $rk0, $ctr0b @ insert existing bytes in top end of result before storing
eor $acc_lb, $acc_lb, $acc_hb @ MODULO - fold into low
st1 { $res1b}, [$output_ptr] @ store all 16B
str $ctr32w, [$counter, #12] @ store the updated counter
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
ext $acc_lb, $acc_lb, $acc_lb, #8
rev64 $acc_lb, $acc_lb
mov x0, $len
st1 { $acc_l.16b }, [$current_tag]
ldp x21, x22, [sp, #16]
ldp x23, x24, [sp, #32]
ldp d8, d9, [sp, #48]
ldp d10, d11, [sp, #64]
ldp d12, d13, [sp, #80]
ldp d14, d15, [sp, #96]
ldp x19, x20, [sp], #112
ret
.L128_enc_ret:
mov w0, #0x0
ret
.size aes_gcm_enc_128_kernel,.-aes_gcm_enc_128_kernel
___
#########################################################################################
# size_t aes_gcm_dec_128_kernel(const unsigned char *in,
# size_t len,
# unsigned char *out,
# const void *key,
# unsigned char ivec[16],
# u64 *Xi);
#
$code.=<<___;
.global aes_gcm_dec_128_kernel
.type aes_gcm_dec_128_kernel,%function
.align 4
aes_gcm_dec_128_kernel:
cbz x1, .L128_dec_ret
stp x19, x20, [sp, #-112]!
mov x16, x4
mov x8, x5
stp x21, x22, [sp, #16]
stp x23, x24, [sp, #32]
stp d8, d9, [sp, #48]
stp d10, d11, [sp, #64]
stp d12, d13, [sp, #80]
stp d14, d15, [sp, #96]
lsr $main_end_input_ptr, $bit_length, #3 @ byte_len
mov $len, $main_end_input_ptr
ldp $ctr96_b64x, $ctr96_t32x, [$counter] @ ctr96_b64, ctr96_t32
-
+#ifdef __AARCH64EB__
+ rev $ctr96_b64x, $ctr96_b64x
+ rev $ctr96_t32x, $ctr96_t32x
+#endif
+ ldp $rk10_l, $rk10_h, [$cc, #160] @ load rk10
+#ifdef __AARCH64EB__
+ ror $rk10_h, $rk10_h, 32
+ ror $rk10_l, $rk10_l, 32
+#endif
sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
- ldr $rk0q, [$cc, #0] @ load rk0
+ ld1 {$rk0s}, [$cc], #16 @ load rk0
and $main_end_input_ptr, $main_end_input_ptr, #0xffffffffffffffc0 @ number of bytes to be processed in main loop (at least 1 byte must be handled by tail)
ld1 { $ctr0b}, [$counter] @ special case vector load initial counter so we can start first AES block as quickly as possible
ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+#ifndef __AARCH64EB__
ext $h2b, $h2b, $h2b, #8
-
+#endif
lsr $rctr32x, $ctr96_t32x, #32
fmov $ctr2d, $ctr96_b64x @ CTR block 2
- ldr $rk1q, [$cc, #16] @ load rk1
+ ld1 {$rk1s}, [$cc], #16 @ load rk1
orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
rev $rctr32w, $rctr32w @ rev_ctr32
fmov $ctr1d, $ctr96_b64x @ CTR block 1
add $rctr32w, $rctr32w, #1 @ increment rev_ctr32
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
rev $ctr32w, $rctr32w @ CTR block 1
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 1
- ldr $rk2q, [$cc, #32] @ load rk2
+ ld1 {$rk2s}, [$cc], #16 @ load rk2
add $rctr32w, $rctr32w, #1 @ CTR block 1
fmov $ctr1.d[1], $ctr32x @ CTR block 1
rev $ctr32w, $rctr32w @ CTR block 2
add $rctr32w, $rctr32w, #1 @ CTR block 2
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 2
fmov $ctr2.d[1], $ctr32x @ CTR block 2
rev $ctr32w, $rctr32w @ CTR block 3
fmov $ctr3d, $ctr96_b64x @ CTR block 3
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 3
add $rctr32w, $rctr32w, #1 @ CTR block 3
fmov $ctr3.d[1], $ctr32x @ CTR block 3
add $end_input_ptr, $input_ptr, $bit_length, lsr #3 @ end_input_ptr
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
- ldr $rk3q, [$cc, #48] @ load rk3
+ ld1 {$rk3s}, [$cc], #16 @ load rk3
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
- ldr $rk6q, [$cc, #96] @ load rk6
+ ld1 {$rk4s}, [$cc], #16 @ load rk4
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
- ldr $rk7q, [$cc, #112] @ load rk7
+ ld1 {$rk5s}, [$cc], #16 @ load rk5
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
- ldr $rk4q, [$cc, #64] @ load rk4
+ ld1 {$rk6s}, [$cc], #16 @ load rk6
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
- ldp $rk10_l, $rk10_h, [$cc, #160] @ load rk10
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
ld1 { $acc_lb}, [$current_tag]
ext $acc_lb, $acc_lb, $acc_lb, #8
rev64 $acc_lb, $acc_lb
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 3
- ldr $rk5q, [$cc, #80] @ load rk5
+ ld1 {$rk7s}, [$cc], #16 @ load rk7
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 3
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
- ldr $rk9q, [$cc, #144] @ load rk9
+ ld1 {$rk8s}, [$cc], #16 @ load rk8
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 4
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 3
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 3
ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+#ifndef __AARCH64EB__
ext $h3b, $h3b, $h3b, #8
-
+#endif
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 4
- ldr $rk8q, [$cc, #128] @ load rk8
+ ld1 {$rk9s}, [$cc], #16 @ load rk9
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 5
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 4
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 4
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 5
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 5
ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+#ifndef __AARCH64EB__
ext $h1b, $h1b, $h1b, #8
-
+#endif
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 5
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 6
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 6
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 6
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 6
trn1 $t0.2d, $h1.2d, $h2.2d @ h2h | h1h
ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+#ifndef __AARCH64EB__
ext $h4b, $h4b, $h4b, #8
+#endif
trn2 $h12k.2d, $h1.2d, $h2.2d @ h2l | h1l
add $main_end_input_ptr, $main_end_input_ptr, $input_ptr
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 7
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 7
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 7
eor $h12k.16b, $h12k.16b, $t0.16b @ h2k | h1k
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 7
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 8
trn2 $h34k.2d, $h3.2d, $h4.2d @ h4l | h3l
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 8
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 8
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 8
trn1 $acc_h.2d, $h3.2d, $h4.2d @ h4h | h3h
aese $ctr2b, $rk9 @ AES block 2 - round 9
aese $ctr3b, $rk9 @ AES block 3 - round 9
aese $ctr0b, $rk9 @ AES block 0 - round 9
cmp $input_ptr, $main_end_input_ptr @ check if we have <= 4 blocks
aese $ctr1b, $rk9 @ AES block 1 - round 9
eor $h34k.16b, $h34k.16b, $acc_h.16b @ h4k | h3k
b.ge .L128_dec_tail @ handle tail
- ldr $res1q, [$input_ptr, #16] @ AES block 1 - load ciphertext
-
- ldr $res0q, [$input_ptr, #0] @ AES block 0 - load ciphertext
+ ld1 {$res0b, $res1b}, [$input_ptr], #32 @ AES block 0 - load ciphertext; AES block 1 - load ciphertext
eor $ctr1b, $res1b, $ctr1b @ AES block 1 - result
- ldr $res2q, [$input_ptr, #32] @ AES block 2 - load ciphertext
+ ld1 {$res2b}, [$input_ptr], #16 @ AES block 2 - load ciphertext
eor $ctr0b, $res0b, $ctr0b @ AES block 0 - result
rev64 $res0b, $res0b @ GHASH block 0
rev $ctr32w, $rctr32w @ CTR block 4
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4
add $rctr32w, $rctr32w, #1 @ CTR block 4
- ldr $res3q, [$input_ptr, #48] @ AES block 3 - load ciphertext
+ ld1 {$res3b}, [$input_ptr], #16 @ AES block 3 - load ciphertext
rev64 $res1b, $res1b @ GHASH block 1
- add $input_ptr, $input_ptr, #64 @ AES input_ptr update
mov $output_l1, $ctr1.d[0] @ AES block 1 - mov low
mov $output_h1, $ctr1.d[1] @ AES block 1 - mov high
mov $output_l0, $ctr0.d[0] @ AES block 0 - mov low
cmp $input_ptr, $main_end_input_ptr @ check if we have <= 8 blocks
mov $output_h0, $ctr0.d[1] @ AES block 0 - mov high
fmov $ctr0d, $ctr96_b64x @ CTR block 4
fmov $ctr0.d[1], $ctr32x @ CTR block 4
rev $ctr32w, $rctr32w @ CTR block 5
eor $output_l1, $output_l1, $rk10_l @ AES block 1 - round 10 low
-
+#ifdef __AARCH64EB__
+ rev $output_l1, $output_l1
+#endif
fmov $ctr1d, $ctr96_b64x @ CTR block 5
add $rctr32w, $rctr32w, #1 @ CTR block 5
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 5
fmov $ctr1.d[1], $ctr32x @ CTR block 5
rev $ctr32w, $rctr32w @ CTR block 6
add $rctr32w, $rctr32w, #1 @ CTR block 6
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 6
eor $output_h1, $output_h1, $rk10_h @ AES block 1 - round 10 high
+#ifdef __AARCH64EB__
+ rev $output_h1, $output_h1
+#endif
eor $output_l0, $output_l0, $rk10_l @ AES block 0 - round 10 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
eor $ctr2b, $res2b, $ctr2b @ AES block 2 - result
eor $output_h0, $output_h0, $rk10_h @ AES block 0 - round 10 high
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES block 0 - store result
stp $output_l1, $output_h1, [$output_ptr], #16 @ AES block 1 - store result
b.ge .L128_dec_prepretail @ do prepretail
.L128_dec_main_loop: @ main loop start
eor $ctr3b, $res3b, $ctr3b @ AES block 4k+3 - result
ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
mov $output_l2, $ctr2.d[0] @ AES block 4k+2 - mov low
pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
mov $output_h2, $ctr2.d[1] @ AES block 4k+2 - mov high
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
fmov $ctr2d, $ctr96_b64x @ CTR block 4k+6
rev64 $res2b, $res2b @ GHASH block 4k+2
fmov $ctr2.d[1], $ctr32x @ CTR block 4k+6
rev $ctr32w, $rctr32w @ CTR block 4k+7
mov $output_l3, $ctr3.d[0] @ AES block 4k+3 - mov low
eor $res0b, $res0b, $acc_lb @ PRE 1
mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
rev64 $res3b, $res3b @ GHASH block 4k+3
pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
mov $output_h3, $ctr3.d[1] @ AES block 4k+3 - mov high
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+7
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
fmov $ctr3d, $ctr96_b64x @ CTR block 4k+7
eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
fmov $ctr3.d[1], $ctr32x @ CTR block 4k+7
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
mov $t0d, $res0.d[1] @ GHASH block 4k - mid
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
eor $output_l3, $output_l3, $rk10_l @ AES block 4k+3 - round 10 low
-
+#ifdef __AARCH64EB__
+ rev $output_l3, $output_l3
+#endif
pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
eor $output_h2, $output_h2, $rk10_h @ AES block 4k+2 - round 10 high
+#ifdef __AARCH64EB__
+ rev $output_h2, $output_h2
+#endif
mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
eor $output_h3, $output_h3, $rk10_h @ AES block 4k+3 - round 10 high
-
+#ifdef __AARCH64EB__
+ rev $output_h3, $output_h3
+#endif
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
eor $output_l2, $output_l2, $rk10_l @ AES block 4k+2 - round 10 low
-
+#ifdef __AARCH64EB__
+ rev $output_l2, $output_l2
+#endif
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
movi $mod_constant.8b, #0xc2
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
stp $output_l2, $output_h2, [$output_ptr], #16 @ AES block 4k+2 - store result
pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
- ldr $res0q, [$input_ptr, #0] @ AES block 4k+4 - load ciphertext
+ ld1 {$res0b}, [$input_ptr], #16 @ AES block 4k+3 - load ciphertext
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
add $rctr32w, $rctr32w, #1 @ CTR block 4k+7
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
stp $output_l3, $output_h3, [$output_ptr], #16 @ AES block 4k+3 - store result
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
rev $ctr32w, $rctr32w @ CTR block 4k+8
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
- ldr $res1q, [$input_ptr, #16] @ AES block 4k+5 - load ciphertext
+ ld1 {$res1b}, [$input_ptr], #16 @ AES block 4k+4 - load ciphertext
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
aese $ctr0b, $rk9 @ AES block 4k+4 - round 9
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+8
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
aese $ctr1b, $rk9 @ AES block 4k+5 - round 9
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
eor $ctr0b, $res0b, $ctr0b @ AES block 4k+4 - result
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
- ldr $res2q, [$input_ptr, #32] @ AES block 4k+6 - load ciphertext
+ ld1 {$res2b}, [$input_ptr], #16 @ AES block 4k+5 - load ciphertext
add $rctr32w, $rctr32w, #1 @ CTR block 4k+8
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
eor $ctr1b, $res1b, $ctr1b @ AES block 4k+5 - result
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
- ldr $res3q, [$input_ptr, #48] @ AES block 4k+3 - load ciphertext
+ ld1 {$res3b}, [$input_ptr], #16 @ AES block 4k+6 - load ciphertext
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
- add $input_ptr, $input_ptr, #64 @ AES input_ptr update
rev64 $res1b, $res1b @ GHASH block 4k+5
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
mov $output_h0, $ctr0.d[1] @ AES block 4k+4 - mov high
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
mov $output_l0, $ctr0.d[0] @ AES block 4k+4 - mov low
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
fmov $ctr0d, $ctr96_b64x @ CTR block 4k+8
pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
fmov $ctr0.d[1], $ctr32x @ CTR block 4k+8
rev $ctr32w, $rctr32w @ CTR block 4k+9
aese $ctr2b, $rk9 @ AES block 4k+6 - round 9
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+9
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
eor $output_h0, $output_h0, $rk10_h @ AES block 4k+4 - round 10 high
-
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
mov $output_h1, $ctr1.d[1] @ AES block 4k+5 - mov high
eor $output_l0, $output_l0, $rk10_l @ AES block 4k+4 - round 10 low
-
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
eor $ctr2b, $res2b, $ctr2b @ AES block 4k+6 - result
mov $output_l1, $ctr1.d[0] @ AES block 4k+5 - mov low
add $rctr32w, $rctr32w, #1 @ CTR block 4k+9
aese $ctr3b, $rk9 @ AES block 4k+7 - round 9
fmov $ctr1d, $ctr96_b64x @ CTR block 4k+9
cmp $input_ptr, $main_end_input_ptr @ LOOP CONTROL
rev64 $res0b, $res0b @ GHASH block 4k+4
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
fmov $ctr1.d[1], $ctr32x @ CTR block 4k+9
rev $ctr32w, $rctr32w @ CTR block 4k+10
add $rctr32w, $rctr32w, #1 @ CTR block 4k+10
eor $output_h1, $output_h1, $rk10_h @ AES block 4k+5 - round 10 high
+#ifdef __AARCH64EB__
+ rev $output_h1, $output_h1
+#endif
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES block 4k+4 - store result
eor $output_l1, $output_l1, $rk10_l @ AES block 4k+5 - round 10 low
+#ifdef __AARCH64EB__
+ rev $output_l1, $output_l1
+#endif
stp $output_l1, $output_h1, [$output_ptr], #16 @ AES block 4k+5 - store result
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+10
b.lt L128_dec_main_loop
.L128_dec_prepretail: @ PREPRETAIL
ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
mov $output_l2, $ctr2.d[0] @ AES block 4k+2 - mov low
mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
eor $ctr3b, $res3b, $ctr3b @ AES block 4k+3 - result
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
mov $output_h2, $ctr2.d[1] @ AES block 4k+2 - mov high
eor $res0b, $res0b, $acc_lb @ PRE 1
fmov $ctr2d, $ctr96_b64x @ CTR block 4k+6
rev64 $res2b, $res2b @ GHASH block 4k+2
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
fmov $ctr2.d[1], $ctr32x @ CTR block 4k+6
rev $ctr32w, $rctr32w @ CTR block 4k+7
mov $output_l3, $ctr3.d[0] @ AES block 4k+3 - mov low
eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
mov $output_h3, $ctr3.d[1] @ AES block 4k+3 - mov high
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+7
pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
mov $t0d, $res0.d[1] @ GHASH block 4k - mid
fmov $ctr3d, $ctr96_b64x @ CTR block 4k+7
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
fmov $ctr3.d[1], $ctr32x @ CTR block 4k+7
pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
rev64 $res3b, $res3b @ GHASH block 4k+3
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
movi $mod_constant.8b, #0xc2
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
eor $output_l3, $output_l3, $rk10_l @ AES block 4k+3 - round 10 low
-
+#ifdef __AARCH64EB__
+ rev $output_l3, $output_l3
+#endif
pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
eor $output_l2, $output_l2, $rk10_l @ AES block 4k+2 - round 10 low
+#ifdef __AARCH64EB__
+ rev $output_l2, $output_l2
+#endif
eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
aese $ctr1b, $rk9 @ AES block 4k+5 - round 9
pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
eor $output_h3, $output_h3, $rk10_h @ AES block 4k+3 - round 10 high
-
+#ifdef __AARCH64EB__
+ rev $output_h3, $output_h3
+#endif
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
eor $output_h2, $output_h2, $rk10_h @ AES block 4k+2 - round 10 high
-
+#ifdef __AARCH64EB__
+ rev $output_h2, $output_h2
+#endif
aese $ctr0b, $rk9 @ AES block 4k+4 - round 9
stp $output_l2, $output_h2, [$output_ptr], #16 @ AES block 4k+2 - store result
aese $ctr2b, $rk9 @ AES block 4k+6 - round 9
add $rctr32w, $rctr32w, #1 @ CTR block 4k+7
stp $output_l3, $output_h3, [$output_ptr], #16 @ AES block 4k+3 - store result
aese $ctr3b, $rk9 @ AES block 4k+7 - round 9
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
.L128_dec_tail: @ TAIL
sub $main_end_input_ptr, $end_input_ptr, $input_ptr @ main_end_input_ptr is number of bytes left to process
ld1 { $res1b}, [$input_ptr], #16 @ AES block 4k+4 - load ciphertext
eor $ctr0b, $res1b, $ctr0b @ AES block 4k+4 - result
mov $output_h0, $ctr0.d[1] @ AES block 4k+4 - mov high
mov $output_l0, $ctr0.d[0] @ AES block 4k+4 - mov low
cmp $main_end_input_ptr, #48
eor $output_h0, $output_h0, $rk10_h @ AES block 4k+4 - round 10 high
-
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
ext $t0.16b, $acc_lb, $acc_lb, #8 @ prepare final partial tag
eor $output_l0, $output_l0, $rk10_l @ AES block 4k+4 - round 10 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
b.gt .L128_dec_blocks_more_than_3
mov $ctr3b, $ctr2b
sub $rctr32w, $rctr32w, #1
movi $acc_l.8b, #0
movi $acc_h.8b, #0
mov $ctr2b, $ctr1b
movi $acc_m.8b, #0
cmp $main_end_input_ptr, #32
b.gt .L128_dec_blocks_more_than_2
cmp $main_end_input_ptr, #16
mov $ctr3b, $ctr1b
sub $rctr32w, $rctr32w, #1
b.gt .L128_dec_blocks_more_than_1
sub $rctr32w, $rctr32w, #1
b .L128_dec_blocks_less_than_1
.L128_dec_blocks_more_than_3: @ blocks left > 3
rev64 $res0b, $res1b @ GHASH final-3 block
ld1 { $res1b}, [$input_ptr], #16 @ AES final-2 block - load ciphertext
eor $res0b, $res0b, $t0.16b @ feed in partial tag
mov $acc_md, $h34k.d[1] @ GHASH final-3 block - mid
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-3 block - store result
eor $ctr0b, $res1b, $ctr1b @ AES final-2 block - result
mov $rk4d, $res0.d[1] @ GHASH final-3 block - mid
mov $output_h0, $ctr0.d[1] @ AES final-2 block - mov high
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH final-3 block - low
mov $output_l0, $ctr0.d[0] @ AES final-2 block - mov low
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH final-3 block - high
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-3 block - mid
movi $t0.8b, #0 @ suppress further partial tag feed in
eor $output_h0, $output_h0, $rk10_h @ AES final-2 block - round 10 high
-
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
pmull $acc_m.1q, $rk4v.1d, $acc_m.1d @ GHASH final-3 block - mid
eor $output_l0, $output_l0, $rk10_l @ AES final-2 block - round 10 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
.L128_dec_blocks_more_than_2: @ blocks left > 2
rev64 $res0b, $res1b @ GHASH final-2 block
ld1 { $res1b}, [$input_ptr], #16 @ AES final-1 block - load ciphertext
eor $res0b, $res0b, $t0.16b @ feed in partial tag
eor $ctr0b, $res1b, $ctr2b @ AES final-1 block - result
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-2 block - store result
mov $rk4d, $res0.d[1] @ GHASH final-2 block - mid
pmull $rk3q1, $res0.1d, $h3.1d @ GHASH final-2 block - low
pmull2 $rk2q1, $res0.2d, $h3.2d @ GHASH final-2 block - high
mov $output_l0, $ctr0.d[0] @ AES final-1 block - mov low
mov $output_h0, $ctr0.d[1] @ AES final-1 block - mov high
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-2 block - mid
movi $t0.8b, #0 @ suppress further partial tag feed in
pmull $rk4v.1q, $rk4v.1d, $h34k.1d @ GHASH final-2 block - mid
eor $output_l0, $output_l0, $rk10_l @ AES final-1 block - round 10 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
eor $acc_lb, $acc_lb, $rk3 @ GHASH final-2 block - low
eor $acc_hb, $acc_hb, $rk2 @ GHASH final-2 block - high
eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-2 block - mid
eor $output_h0, $output_h0, $rk10_h @ AES final-1 block - round 10 high
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
.L128_dec_blocks_more_than_1: @ blocks left > 1
rev64 $res0b, $res1b @ GHASH final-1 block
ld1 { $res1b}, [$input_ptr], #16 @ AES final block - load ciphertext
eor $res0b, $res0b, $t0.16b @ feed in partial tag
mov $rk4d, $res0.d[1] @ GHASH final-1 block - mid
eor $ctr0b, $res1b, $ctr3b @ AES final block - result
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-1 block - mid
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-1 block - store result
mov $output_l0, $ctr0.d[0] @ AES final block - mov low
mov $output_h0, $ctr0.d[1] @ AES final block - mov high
ins $rk4v.d[1], $rk4v.d[0] @ GHASH final-1 block - mid
pmull $rk3q1, $res0.1d, $h2.1d @ GHASH final-1 block - low
pmull2 $rk2q1, $res0.2d, $h2.2d @ GHASH final-1 block - high
pmull2 $rk4v.1q, $rk4v.2d, $h12k.2d @ GHASH final-1 block - mid
movi $t0.8b, #0 @ suppress further partial tag feed in
eor $acc_lb, $acc_lb, $rk3 @ GHASH final-1 block - low
eor $acc_hb, $acc_hb, $rk2 @ GHASH final-1 block - high
eor $output_h0, $output_h0, $rk10_h @ AES final block - round 10 high
-
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
eor $output_l0, $output_l0, $rk10_l @ AES final block - round 10 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-1 block - mid
.L128_dec_blocks_less_than_1: @ blocks left <= 1
mvn $rk10_h, xzr @ rk10_h = 0xffffffffffffffff
and $bit_length, $bit_length, #127 @ bit_length %= 128
mvn $rk10_l, xzr @ rk10_l = 0xffffffffffffffff
sub $bit_length, $bit_length, #128 @ bit_length -= 128
neg $bit_length, $bit_length @ bit_length = 128 - #bits in input (in range [1,128])
and $bit_length, $bit_length, #127 @ bit_length %= 128
lsr $rk10_h, $rk10_h, $bit_length @ rk10_h is mask for top 64b of last block
cmp $bit_length, #64
csel $ctr96_b64x, $rk10_h, xzr, lt
csel $ctr32x, $rk10_l, $rk10_h, lt
fmov $ctr0d, $ctr32x @ ctr0b is mask for last block
mov $ctr0.d[1], $ctr96_b64x
and $res1b, $res1b, $ctr0b @ possibly partial last block has zeroes in highest bits
rev64 $res0b, $res1b @ GHASH final block
eor $res0b, $res0b, $t0.16b @ feed in partial tag
ldp $end_input_ptr, $main_end_input_ptr, [$output_ptr] @ load existing bytes we need to not overwrite
and $output_h0, $output_h0, $ctr96_b64x
pmull2 $rk2q1, $res0.2d, $h1.2d @ GHASH final block - high
mov $t0d, $res0.d[1] @ GHASH final block - mid
eor $t0.8b, $t0.8b, $res0.8b @ GHASH final block - mid
eor $acc_hb, $acc_hb, $rk2 @ GHASH final block - high
pmull $t0.1q, $t0.1d, $h12k.1d @ GHASH final block - mid
pmull $rk3q1, $res0.1d, $h1.1d @ GHASH final block - low
bic $end_input_ptr, $end_input_ptr, $ctr32x @ mask out low existing bytes
and $output_l0, $output_l0, $ctr32x
+#ifndef __AARCH64EB__
rev $ctr32w, $rctr32w
+#else
+ mov $ctr32w, $rctr32w
+#endif
eor $acc_mb, $acc_mb, $t0.16b @ GHASH final block - mid
movi $mod_constant.8b, #0xc2
eor $acc_lb, $acc_lb, $rk3 @ GHASH final block - low
bic $main_end_input_ptr, $main_end_input_ptr, $ctr96_b64x @ mask out high existing bytes
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
orr $output_l0, $output_l0, $end_input_ptr
str $ctr32w, [$counter, #12] @ store the updated counter
orr $output_h0, $output_h0, $main_end_input_ptr
stp $output_l0, $output_h0, [$output_ptr]
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
ext $acc_lb, $acc_lb, $acc_lb, #8
rev64 $acc_lb, $acc_lb
mov x0, $len
st1 { $acc_l.16b }, [$current_tag]
ldp x21, x22, [sp, #16]
ldp x23, x24, [sp, #32]
ldp d8, d9, [sp, #48]
ldp d10, d11, [sp, #64]
ldp d12, d13, [sp, #80]
ldp d14, d15, [sp, #96]
ldp x19, x20, [sp], #112
ret
.L128_dec_ret:
mov w0, #0x0
ret
.size aes_gcm_dec_128_kernel,.-aes_gcm_dec_128_kernel
___
}
{
my ($end_input_ptr,$main_end_input_ptr,$input_l0,$input_h0)=map("x$_",(4..7));
my ($input_l1,$input_h1,$input_l2,$input_h2,$input_l3,$input_h3)=map("x$_",(19..24));
my ($output_l1,$output_h1,$output_l2,$output_h2,$output_l3,$output_h3)=map("x$_",(19..24));
my ($output_l0,$output_h0)=map("x$_",(6..7));
my $ctr32w="w9";
my ($ctr32x,$ctr96_b64x,$ctr96_t32x,$rctr32x,$rk12_l,$rk12_h,$len)=map("x$_",(9..15));
my ($ctr96_t32w,$rctr32w)=map("w$_",(11..12));
my ($ctr0b,$ctr1b,$ctr2b,$ctr3b,$res0b,$res1b,$res2b,$res3b)=map("v$_.16b",(0..7));
my ($ctr0,$ctr1,$ctr2,$ctr3,$res0,$res1,$res2,$res3)=map("v$_",(0..7));
my ($ctr0d,$ctr1d,$ctr2d,$ctr3d,$res0d,$res1d,$res2d,$res3d)=map("d$_",(0..7));
my ($res0q,$res1q,$res2q,$res3q)=map("q$_",(4..7));
my ($acc_hb,$acc_mb,$acc_lb)=map("v$_.16b",(9..11));
my ($acc_h,$acc_m,$acc_l)=map("v$_",(9..11));
my ($acc_hd,$acc_md,$acc_ld)=map("d$_",(9..11));
my ($h1,$h2,$h3,$h4,$h12k,$h34k)=map("v$_",(12..17));
my ($h1q,$h2q,$h3q,$h4q)=map("q$_",(12..15));
my ($h1b,$h2b,$h3b,$h4b)=map("v$_.16b",(12..15));
my $t0="v8";
my $t0d="d8";
my $t3="v4";
my $t3d="d4";
my ($t1,$t2)=map("v$_",(30..31));
my ($t1d,$t2d)=map("d$_",(30..31));
my $t4="v30";
my $t4d="d30";
my $t5="v8";
my $t5d="d8";
my $t6="v31";
my $t6d="d31";
my $t7="v5";
my $t7d="d5";
my $t8="v6";
my $t8d="d6";
my $t9="v30";
my $t9d="d30";
my ($ctr_t0,$ctr_t1,$ctr_t2,$ctr_t3)=map("v$_",(4..7));
my ($ctr_t0d,$ctr_t1d,$ctr_t2d,$ctr_t3d)=map("d$_",(4..7));
my ($ctr_t0b,$ctr_t1b,$ctr_t2b,$ctr_t3b)=map("v$_.16b",(4..7));
my $mod_constantd="d8";
my $mod_constant="v8";
my $mod_t="v31";
my ($rk0,$rk1,$rk2,$rk3,$rk4,$rk5,$rk6,$rk7,$rk8,$rk9,$rk10,$rk11)=map("v$_.16b",(18..29));
my ($rk0q,$rk1q,$rk2q,$rk3q,$rk4q,$rk5q,$rk6q,$rk7q,$rk8q,$rk9q,$rk10q,$rk11q)=map("q$_",(18..29));
+my ($rk0s,$rk1s,$rk2s,$rk3s,$rk4s,$rk5s,$rk6s,$rk7s,$rk8s,$rk9s,$rk10s,$rk11s)=map("v$_.4s",(18..29));
my $rk2q1="v20.1q";
my $rk3q1="v21.1q";
my $rk4v="v22";
my $rk4d="d22";
#########################################################################################
# size_t aes_gcm_enc_192_kernel(const unsigned char *in,
# size_t len,
# unsigned char *out,
# const void *key,
# unsigned char ivec[16],
# u64 *Xi);
#
$code.=<<___;
.global aes_gcm_enc_192_kernel
.type aes_gcm_enc_192_kernel,%function
.align 4
aes_gcm_enc_192_kernel:
cbz x1, .L192_enc_ret
stp x19, x20, [sp, #-112]!
mov x16, x4
mov x8, x5
stp x21, x22, [sp, #16]
stp x23, x24, [sp, #32]
stp d8, d9, [sp, #48]
stp d10, d11, [sp, #64]
stp d12, d13, [sp, #80]
stp d14, d15, [sp, #96]
ldp $ctr96_b64x, $ctr96_t32x, [$counter] @ ctr96_b64, ctr96_t32
+#ifdef __AARCH64EB__
+ rev $ctr96_b64x, $ctr96_b64x
+ rev $ctr96_t32x, $ctr96_t32x
+#endif
+ ldp $rk12_l, $rk12_h, [$cc, #192] @ load rk12
+#ifdef __AARCH64EB__
+ ror $rk12_l, $rk12_l, #32
+ ror $rk12_h, $rk12_h, #32
+#endif
+ ld1 {$rk0s}, [$cc], #16 @ load rk0
- ldr $rk5q, [$cc, #80] @ load rk5
-
- ldr $rk4q, [$cc, #64] @ load rk4
+ ld1 {$rk1s}, [$cc], #16 @ load rk1
- ldr $rk8q, [$cc, #128] @ load rk8
+ ld1 {$rk2s}, [$cc], #16 @ load rk2
lsr $rctr32x, $ctr96_t32x, #32
- ldr $rk6q, [$cc, #96] @ load rk6
+ ld1 {$rk3s}, [$cc], #16 @ load rk3
orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
- ldr $rk7q, [$cc, #112] @ load rk7
+ ld1 {$rk4s}, [$cc], #16 @ load rk4
rev $rctr32w, $rctr32w @ rev_ctr32
add $rctr32w, $rctr32w, #1 @ increment rev_ctr32
fmov $ctr3d, $ctr96_b64x @ CTR block 3
rev $ctr32w, $rctr32w @ CTR block 1
add $rctr32w, $rctr32w, #1 @ CTR block 1
fmov $ctr1d, $ctr96_b64x @ CTR block 1
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 1
ld1 { $ctr0b}, [$counter] @ special case vector load initial counter so we can start first AES block as quickly as possible
fmov $ctr1.d[1], $ctr32x @ CTR block 1
rev $ctr32w, $rctr32w @ CTR block 2
add $rctr32w, $rctr32w, #1 @ CTR block 2
fmov $ctr2d, $ctr96_b64x @ CTR block 2
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 2
fmov $ctr2.d[1], $ctr32x @ CTR block 2
rev $ctr32w, $rctr32w @ CTR block 3
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 3
- ldr $rk0q, [$cc, #0] @ load rk0
+ ld1 {$rk5s}, [$cc], #16 @ load rk5
fmov $ctr3.d[1], $ctr32x @ CTR block 3
- ldr $rk3q, [$cc, #48] @ load rk3
-
- ldp $rk12_l, $rk12_h, [$cc, #192] @ load rk12
+ ld1 {$rk6s}, [$cc], #16 @ load rk6
- ldr $rk1q, [$cc, #16] @ load rk1
+ ld1 {$rk7s}, [$cc], #16 @ load rk7
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
ld1 { $acc_lb}, [$current_tag]
ext $acc_lb, $acc_lb, $acc_lb, #8
rev64 $acc_lb, $acc_lb
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
- ldr $rk11q, [$cc, #176] @ load rk11
+ ld1 {$rk8s}, [$cc], #16 @ load rk8
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+#ifndef __AARCH64EB__
ext $h4b, $h4b, $h4b, #8
-
+#endif
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
- ldr $rk2q, [$cc, #32] @ load rk2
+ ld1 {$rk9s}, [$cc], #16 @ load rk9
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
- ldr $rk10q, [$cc, #160] @ load rk10
+ ld1 {$rk10s}, [$cc], #16 @ load rk10
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+#ifndef __AARCH64EB__
ext $h1b, $h1b, $h1b, #8
-
+#endif
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
- ldr $rk9q, [$cc, #144] @ load rk9
+ ld1 {$rk11s}, [$cc], #16 @ load rk11
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+#ifndef __AARCH64EB__
ext $h3b, $h3b, $h3b, #8
-
+#endif
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 3
trn1 $acc_h.2d, $h3.2d, $h4.2d @ h4h | h3h
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 3
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
trn2 $h34k.2d, $h3.2d, $h4.2d @ h4l | h3l
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 4
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 3
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 3
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 5
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 4
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 4
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 6
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 4
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 5
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 5
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 5
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 6
ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+#ifndef __AARCH64EB__
ext $h2b, $h2b, $h2b, #8
-
+#endif
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 6
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 6
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 7
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 7
trn2 $h12k.2d, $h1.2d, $h2.2d @ h2l | h1l
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 7
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 8
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 7
trn1 $t0.2d, $h1.2d, $h2.2d @ h2h | h1h
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 8
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 8
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 8
aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 9
aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 9
aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 9
aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 9
aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 10
aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 10
aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 10
lsr $main_end_input_ptr, $bit_length, #3 @ byte_len
mov $len, $main_end_input_ptr
aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 10
sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
eor $h12k.16b, $h12k.16b, $t0.16b @ h2k | h1k
and $main_end_input_ptr, $main_end_input_ptr, #0xffffffffffffffc0 @ number of bytes to be processed in main loop (at least 1 byte must be handled by tail)
eor $h34k.16b, $h34k.16b, $acc_h.16b @ h4k | h3k
aese $ctr2b, $rk11 @ AES block 2 - round 11
add $end_input_ptr, $input_ptr, $bit_length, lsr #3 @ end_input_ptr
add $main_end_input_ptr, $main_end_input_ptr, $input_ptr
aese $ctr1b, $rk11 @ AES block 1 - round 11
cmp $input_ptr, $main_end_input_ptr @ check if we have <= 4 blocks
aese $ctr0b, $rk11 @ AES block 0 - round 11
add $rctr32w, $rctr32w, #1 @ CTR block 3
aese $ctr3b, $rk11 @ AES block 3 - round 11
b.ge .L192_enc_tail @ handle tail
rev $ctr32w, $rctr32w @ CTR block 4
ldp $input_l0, $input_h0, [$input_ptr, #0] @ AES block 0 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4
ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 2 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l2, $input_l2
+ rev $input_h2, $input_h2
+#endif
ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 3 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l3, $input_l3
+ rev $input_h3, $input_h3
+#endif
ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 1 - load plaintext
+#ifdef __AARCH64EB__
+ rev $input_l1, $input_l1
+ rev $input_h1, $input_h1
+#endif
add $input_ptr, $input_ptr, #64 @ AES input_ptr update
cmp $input_ptr, $main_end_input_ptr @ check if we have <= 8 blocks
eor $input_l0, $input_l0, $rk12_l @ AES block 0 - round 12 low
eor $input_h0, $input_h0, $rk12_h @ AES block 0 - round 12 high
eor $input_h2, $input_h2, $rk12_h @ AES block 2 - round 12 high
fmov $ctr_t0d, $input_l0 @ AES block 0 - mov low
eor $input_h3, $input_h3, $rk12_h @ AES block 3 - round 12 high
fmov $ctr_t0.d[1], $input_h0 @ AES block 0 - mov high
eor $input_l2, $input_l2, $rk12_l @ AES block 2 - round 12 low
eor $input_l1, $input_l1, $rk12_l @ AES block 1 - round 12 low
fmov $ctr_t1d, $input_l1 @ AES block 1 - mov low
eor $input_h1, $input_h1, $rk12_h @ AES block 1 - round 12 high
fmov $ctr_t1.d[1], $input_h1 @ AES block 1 - mov high
eor $input_l3, $input_l3, $rk12_l @ AES block 3 - round 12 low
fmov $ctr_t2d, $input_l2 @ AES block 2 - mov low
add $rctr32w, $rctr32w, #1 @ CTR block 4
eor $res0b, $ctr_t0b, $ctr0b @ AES block 0 - result
fmov $ctr0d, $ctr96_b64x @ CTR block 4
fmov $ctr0.d[1], $ctr32x @ CTR block 4
rev $ctr32w, $rctr32w @ CTR block 5
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 5
add $rctr32w, $rctr32w, #1 @ CTR block 5
fmov $ctr_t3d, $input_l3 @ AES block 3 - mov low
st1 { $res0b}, [$output_ptr], #16 @ AES block 0 - store result
fmov $ctr_t2.d[1], $input_h2 @ AES block 2 - mov high
eor $res1b, $ctr_t1b, $ctr1b @ AES block 1 - result
fmov $ctr1d, $ctr96_b64x @ CTR block 5
st1 { $res1b}, [$output_ptr], #16 @ AES block 1 - store result
fmov $ctr_t3.d[1], $input_h3 @ AES block 3 - mov high
fmov $ctr1.d[1], $ctr32x @ CTR block 5
rev $ctr32w, $rctr32w @ CTR block 6
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 6
add $rctr32w, $rctr32w, #1 @ CTR block 6
eor $res2b, $ctr_t2b, $ctr2b @ AES block 2 - result
fmov $ctr2d, $ctr96_b64x @ CTR block 6
fmov $ctr2.d[1], $ctr32x @ CTR block 6
rev $ctr32w, $rctr32w @ CTR block 7
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 7
st1 { $res2b}, [$output_ptr], #16 @ AES block 2 - store result
eor $res3b, $ctr_t3b, $ctr3b @ AES block 3 - result
st1 { $res3b}, [$output_ptr], #16 @ AES block 3 - store result
b.ge .L192_enc_prepretail @ do prepretail
.L192_enc_main_loop: @ main loop start
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
rev64 $res1b, $res1b @ GHASH block 4k+1 (t0 and t1 free)
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 4k+5 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l1, $input_l1
+ rev $input_h1, $input_h1
+#endif
ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
fmov $ctr3d, $ctr96_b64x @ CTR block 4k+3
rev64 $res0b, $res0b @ GHASH block 4k (only t0 is free)
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
fmov $ctr3.d[1], $ctr32x @ CTR block 4k+3
pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
rev64 $res3b, $res3b @ GHASH block 4k+3 (t0, t1, t2 and t3 free)
ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 4k+6 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l2, $input_l2
+ rev $input_h2, $input_h2
+#endif
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 4k+3 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l3, $input_l3
+ rev $input_h3, $input_h3
+#endif
pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
eor $res0b, $res0b, $acc_lb @ PRE 1
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
rev64 $res2b, $res2b @ GHASH block 4k+2 (t0, t1, and t2 free)
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
eor $input_h3, $input_h3, $rk12_h @ AES block 4k+3 - round 12 high
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
mov $t0d, $res0.d[1] @ GHASH block 4k - mid
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
eor $input_l2, $input_l2, $rk12_l @ AES block 4k+6 - round 12 low
eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
eor $input_l1, $input_l1, $rk12_l @ AES block 4k+5 - round 12 low
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
eor $input_h1, $input_h1, $rk12_h @ AES block 4k+5 - round 12 high
ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
add $rctr32w, $rctr32w, #1 @ CTR block 4k+3
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
eor $input_h2, $input_h2, $rk12_h @ AES block 4k+6 - round 12 high
pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
eor $input_l3, $input_l3, $rk12_l @ AES block 4k+3 - round 12 low
mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
rev $ctr32w, $rctr32w @ CTR block 4k+8
pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+8
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
ldp $input_l0, $input_h0, [$input_ptr, #0] @ AES block 4k+4 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
add $input_ptr, $input_ptr, #64 @ AES input_ptr update
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
movi $mod_constant.8b, #0xc2
pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
eor $input_h0, $input_h0, $rk12_h @ AES block 4k+4 - round 12 high
eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
eor $input_l0, $input_l0, $rk12_l @ AES block 4k+4 - round 12 low
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
fmov $ctr_t1d, $input_l1 @ AES block 4k+5 - mov low
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
fmov $ctr_t1.d[1], $input_h1 @ AES block 4k+5 - mov high
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
cmp $input_ptr, $main_end_input_ptr @ LOOP CONTROL
fmov $ctr_t0d, $input_l0 @ AES block 4k+4 - mov low
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
fmov $ctr_t0.d[1], $input_h0 @ AES block 4k+4 - mov high
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
fmov $ctr_t3d, $input_l3 @ AES block 4k+3 - mov low
eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
add $rctr32w, $rctr32w, #1 @ CTR block 4k+8
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
fmov $ctr_t3.d[1], $input_h3 @ AES block 4k+3 - mov high
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
fmov $ctr_t2d, $input_l2 @ AES block 4k+6 - mov low
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
aese $ctr0b, $rk11 @ AES block 4k+4 - round 11
aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
eor $res0b, $ctr_t0b, $ctr0b @ AES block 4k+4 - result
fmov $ctr0d, $ctr96_b64x @ CTR block 4k+8
aese $ctr1b, $rk11 @ AES block 4k+5 - round 11
fmov $ctr0.d[1], $ctr32x @ CTR block 4k+8
rev $ctr32w, $rctr32w @ CTR block 4k+9
pmull $acc_h.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
fmov $ctr_t2.d[1], $input_h2 @ AES block 4k+6 - mov high
st1 { $res0b}, [$output_ptr], #16 @ AES block 4k+4 - store result
aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+9
eor $res1b, $ctr_t1b, $ctr1b @ AES block 4k+5 - result
add $rctr32w, $rctr32w, #1 @ CTR block 4k+9
fmov $ctr1d, $ctr96_b64x @ CTR block 4k+9
aese $ctr2b, $rk11 @ AES block 4k+6 - round 11
fmov $ctr1.d[1], $ctr32x @ CTR block 4k+9
rev $ctr32w, $rctr32w @ CTR block 4k+10
add $rctr32w, $rctr32w, #1 @ CTR block 4k+10
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+10
st1 { $res1b}, [$output_ptr], #16 @ AES block 4k+5 - store result
eor $acc_lb, $acc_lb, $acc_hb @ MODULO - fold into low
aese $ctr3b, $rk11 @ AES block 4k+7 - round 11
eor $res2b, $ctr_t2b, $ctr2b @ AES block 4k+6 - result
fmov $ctr2d, $ctr96_b64x @ CTR block 4k+10
st1 { $res2b}, [$output_ptr], #16 @ AES block 4k+6 - store result
fmov $ctr2.d[1], $ctr32x @ CTR block 4k+10
rev $ctr32w, $rctr32w @ CTR block 4k+11
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+11
eor $res3b, $ctr_t3b, $ctr3b @ AES block 4k+3 - result
st1 { $res3b}, [$output_ptr], #16 @ AES block 4k+3 - store result
b.lt .L192_enc_main_loop
.L192_enc_prepretail: @ PREPRETAIL
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
rev64 $res0b, $res0b @ GHASH block 4k (only t0 is free)
fmov $ctr3d, $ctr96_b64x @ CTR block 4k+3
ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
add $rctr32w, $rctr32w, #1 @ CTR block 4k+3
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
rev64 $res1b, $res1b @ GHASH block 4k+1 (t0 and t1 free)
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
fmov $ctr3.d[1], $ctr32x @ CTR block 4k+3
eor $res0b, $res0b, $acc_lb @ PRE 1
mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
rev64 $res2b, $res2b @ GHASH block 4k+2 (t0, t1, and t2 free)
pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
mov $t0d, $res0.d[1] @ GHASH block 4k - mid
pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
rev64 $res3b, $res3b @ GHASH block 4k+3 (t0, t1, t2 and t3 free)
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
movi $mod_constant.8b, #0xc2
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
eor $acc_mb, $acc_mb, $acc_hb @ karatsuba tidy up
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
eor $acc_mb, $acc_mb, $acc_lb
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
pmull $t1.1q, $acc_h.1d, $mod_constant.1d
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
ext $acc_hb, $acc_hb, $acc_hb, #8
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
eor $acc_mb, $acc_mb, $t1.16b
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
eor $acc_mb, $acc_mb, $acc_hb
aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
pmull $t1.1q, $acc_m.1d, $mod_constant.1d
ext $acc_mb, $acc_mb, $acc_mb, #8
aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
eor $acc_lb, $acc_lb, $t1.16b
aese $ctr0b, $rk11 @ AES block 4k+4 - round 11
aese $ctr3b, $rk11 @ AES block 4k+7 - round 11
aese $ctr2b, $rk11 @ AES block 4k+6 - round 11
aese $ctr1b, $rk11 @ AES block 4k+5 - round 11
eor $acc_lb, $acc_lb, $acc_mb
.L192_enc_tail: @ TAIL
sub $main_end_input_ptr, $end_input_ptr, $input_ptr @ main_end_input_ptr is number of bytes left to process
ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES block 4k+4 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
eor $input_l0, $input_l0, $rk12_l @ AES block 4k+4 - round 12 low
eor $input_h0, $input_h0, $rk12_h @ AES block 4k+4 - round 12 high
fmov $ctr_t0d, $input_l0 @ AES block 4k+4 - mov low
fmov $ctr_t0.d[1], $input_h0 @ AES block 4k+4 - mov high
cmp $main_end_input_ptr, #48
eor $res1b, $ctr_t0b, $ctr0b @ AES block 4k+4 - result
ext $t0.16b, $acc_lb, $acc_lb, #8 @ prepare final partial tag
b.gt .L192_enc_blocks_more_than_3
sub $rctr32w, $rctr32w, #1
movi $acc_m.8b, #0
mov $ctr3b, $ctr2b
movi $acc_h.8b, #0
cmp $main_end_input_ptr, #32
mov $ctr2b, $ctr1b
movi $acc_l.8b, #0
b.gt .L192_enc_blocks_more_than_2
sub $rctr32w, $rctr32w, #1
mov $ctr3b, $ctr1b
cmp $main_end_input_ptr, #16
b.gt .L192_enc_blocks_more_than_1
sub $rctr32w, $rctr32w, #1
b .L192_enc_blocks_less_than_1
.L192_enc_blocks_more_than_3: @ blocks left > 3
st1 { $res1b}, [$output_ptr], #16 @ AES final-3 block - store result
ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final-2 block - load input low & high
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
rev64 $res0b, $res1b @ GHASH final-3 block
eor $input_l0, $input_l0, $rk12_l @ AES final-2 block - round 12 low
eor $res0b, $res0b, $t0.16b @ feed in partial tag
eor $input_h0, $input_h0, $rk12_h @ AES final-2 block - round 12 high
fmov $res1d, $input_l0 @ AES final-2 block - mov low
fmov $res1.d[1], $input_h0 @ AES final-2 block - mov high
mov $rk4d, $res0.d[1] @ GHASH final-3 block - mid
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH final-3 block - low
mov $acc_md, $h34k.d[1] @ GHASH final-3 block - mid
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-3 block - mid
movi $t0.8b, #0 @ suppress further partial tag feed in
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH final-3 block - high
pmull $acc_m.1q, $rk4v.1d, $acc_m.1d @ GHASH final-3 block - mid
eor $res1b, $res1b, $ctr1b @ AES final-2 block - result
.L192_enc_blocks_more_than_2: @ blocks left > 2
st1 { $res1b}, [$output_ptr], #16 @ AES final-2 block - store result
rev64 $res0b, $res1b @ GHASH final-2 block
ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final-1 block - load input low & high
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
eor $res0b, $res0b, $t0.16b @ feed in partial tag
eor $input_h0, $input_h0, $rk12_h @ AES final-1 block - round 12 high
pmull2 $rk2q1, $res0.2d, $h3.2d @ GHASH final-2 block - high
mov $rk4d, $res0.d[1] @ GHASH final-2 block - mid
pmull $rk3q1, $res0.1d, $h3.1d @ GHASH final-2 block - low
eor $input_l0, $input_l0, $rk12_l @ AES final-1 block - round 12 low
fmov $res1d, $input_l0 @ AES final-1 block - mov low
fmov $res1.d[1], $input_h0 @ AES final-1 block - mov high
eor $acc_hb, $acc_hb, $rk2 @ GHASH final-2 block - high
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-2 block - mid
eor $acc_lb, $acc_lb, $rk3 @ GHASH final-2 block - low
pmull $rk4v.1q, $rk4v.1d, $h34k.1d @ GHASH final-2 block - mid
movi $t0.8b, #0 @ suppress further partial tag feed in
eor $res1b, $res1b, $ctr2b @ AES final-1 block - result
eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-2 block - mid
.L192_enc_blocks_more_than_1: @ blocks left > 1
st1 { $res1b}, [$output_ptr], #16 @ AES final-1 block - store result
ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final block - load input low & high
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
rev64 $res0b, $res1b @ GHASH final-1 block
eor $input_l0, $input_l0, $rk12_l @ AES final block - round 12 low
eor $res0b, $res0b, $t0.16b @ feed in partial tag
movi $t0.8b, #0 @ suppress further partial tag feed in
mov $rk4d, $res0.d[1] @ GHASH final-1 block - mid
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-1 block - mid
eor $input_h0, $input_h0, $rk12_h @ AES final block - round 12 high
fmov $res1d, $input_l0 @ AES final block - mov low
pmull2 $rk2q1, $res0.2d, $h2.2d @ GHASH final-1 block - high
fmov $res1.d[1], $input_h0 @ AES final block - mov high
ins $rk4v.d[1], $rk4v.d[0] @ GHASH final-1 block - mid
eor $acc_hb, $acc_hb, $rk2 @ GHASH final-1 block - high
pmull $rk3q1, $res0.1d, $h2.1d @ GHASH final-1 block - low
pmull2 $rk4v.1q, $rk4v.2d, $h12k.2d @ GHASH final-1 block - mid
eor $res1b, $res1b, $ctr3b @ AES final block - result
eor $acc_lb, $acc_lb, $rk3 @ GHASH final-1 block - low
eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-1 block - mid
.L192_enc_blocks_less_than_1: @ blocks left <= 1
ld1 { $rk0}, [$output_ptr] @ load existing bytes where the possibly partial last block is to be stored
+#ifndef __AARCH64EB__
rev $ctr32w, $rctr32w
+#else
+ mov $ctr32w, $rctr32w
+#endif
and $bit_length, $bit_length, #127 @ bit_length %= 128
sub $bit_length, $bit_length, #128 @ bit_length -= 128
mvn $rk12_h, xzr @ rk12_h = 0xffffffffffffffff
neg $bit_length, $bit_length @ bit_length = 128 - #bits in input (in range [1,128])
mvn $rk12_l, xzr @ rk12_l = 0xffffffffffffffff
and $bit_length, $bit_length, #127 @ bit_length %= 128
lsr $rk12_h, $rk12_h, $bit_length @ rk12_h is mask for top 64b of last block
cmp $bit_length, #64
csel $input_l0, $rk12_l, $rk12_h, lt
csel $input_h0, $rk12_h, xzr, lt
fmov $ctr0d, $input_l0 @ ctr0b is mask for last block
fmov $ctr0.d[1], $input_h0
and $res1b, $res1b, $ctr0b @ possibly partial last block has zeroes in highest bits
rev64 $res0b, $res1b @ GHASH final block
eor $res0b, $res0b, $t0.16b @ feed in partial tag
mov $t0d, $res0.d[1] @ GHASH final block - mid
pmull $rk3q1, $res0.1d, $h1.1d @ GHASH final block - low
pmull2 $rk2q1, $res0.2d, $h1.2d @ GHASH final block - high
eor $t0.8b, $t0.8b, $res0.8b @ GHASH final block - mid
eor $acc_lb, $acc_lb, $rk3 @ GHASH final block - low
eor $acc_hb, $acc_hb, $rk2 @ GHASH final block - high
pmull $t0.1q, $t0.1d, $h12k.1d @ GHASH final block - mid
eor $acc_mb, $acc_mb, $t0.16b @ GHASH final block - mid
movi $mod_constant.8b, #0xc2
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
bif $res1b, $rk0, $ctr0b @ insert existing bytes in top end of result before storing
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
pmull $acc_h.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
eor $acc_lb, $acc_lb, $acc_hb @ MODULO - fold into low
str $ctr32w, [$counter, #12] @ store the updated counter
st1 { $res1b}, [$output_ptr] @ store all 16B
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
ext $acc_lb, $acc_lb, $acc_lb, #8
rev64 $acc_lb, $acc_lb
mov x0, $len
st1 { $acc_l.16b }, [$current_tag]
ldp x21, x22, [sp, #16]
ldp x23, x24, [sp, #32]
ldp d8, d9, [sp, #48]
ldp d10, d11, [sp, #64]
ldp d12, d13, [sp, #80]
ldp d14, d15, [sp, #96]
ldp x19, x20, [sp], #112
ret
.L192_enc_ret:
mov w0, #0x0
ret
.size aes_gcm_enc_192_kernel,.-aes_gcm_enc_192_kernel
___
#########################################################################################
# size_t aes_gcm_dec_192_kernel(const unsigned char *in,
# size_t len,
# unsigned char *out,
# const void *key,
# unsigned char ivec[16],
# u64 *Xi);
#
$code.=<<___;
.global aes_gcm_dec_192_kernel
.type aes_gcm_dec_192_kernel,%function
.align 4
aes_gcm_dec_192_kernel:
cbz x1, .L192_dec_ret
stp x19, x20, [sp, #-112]!
mov x16, x4
mov x8, x5
stp x21, x22, [sp, #16]
stp x23, x24, [sp, #32]
stp d8, d9, [sp, #48]
stp d10, d11, [sp, #64]
stp d12, d13, [sp, #80]
stp d14, d15, [sp, #96]
add $end_input_ptr, $input_ptr, $bit_length, lsr #3 @ end_input_ptr
ldp $ctr96_b64x, $ctr96_t32x, [$counter] @ ctr96_b64, ctr96_t32
-
+#ifdef __AARCH64EB__
+ rev $ctr96_b64x, $ctr96_b64x
+ rev $ctr96_t32x, $ctr96_t32x
+#endif
+ ldp $rk12_l, $rk12_h, [$cc, #192] @ load rk12
+#ifdef __AARCH64EB__
+ ror $rk12_l, $rk12_l, #32
+ ror $rk12_h, $rk12_h, #32
+#endif
ld1 { $ctr0b}, [$counter] @ special case vector load initial counter so we can start first AES block as quickly as possible
- ldr $rk0q, [$cc, #0] @ load rk0
+ ld1 {$rk0s}, [$cc], #16 @ load rk0
lsr $main_end_input_ptr, $bit_length, #3 @ byte_len
mov $len, $main_end_input_ptr
- ldr $rk2q, [$cc, #32] @ load rk2
+ ld1 {$rk1s}, [$cc], #16 @ load rk1
lsr $rctr32x, $ctr96_t32x, #32
orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
fmov $ctr3d, $ctr96_b64x @ CTR block 3
rev $rctr32w, $rctr32w @ rev_ctr32
fmov $ctr1d, $ctr96_b64x @ CTR block 1
add $rctr32w, $rctr32w, #1 @ increment rev_ctr32
- ldr $rk1q, [$cc, #16] @ load rk1
+ ld1 {$rk2s}, [$cc], #16 @ load rk2
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
rev $ctr32w, $rctr32w @ CTR block 1
add $rctr32w, $rctr32w, #1 @ CTR block 1
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 1
- ldr $rk3q, [$cc, #48] @ load rk3
+ ld1 {$rk3s}, [$cc], #16 @ load rk3
fmov $ctr1.d[1], $ctr32x @ CTR block 1
rev $ctr32w, $rctr32w @ CTR block 2
add $rctr32w, $rctr32w, #1 @ CTR block 2
fmov $ctr2d, $ctr96_b64x @ CTR block 2
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 2
fmov $ctr2.d[1], $ctr32x @ CTR block 2
rev $ctr32w, $rctr32w @ CTR block 3
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 3
fmov $ctr3.d[1], $ctr32x @ CTR block 3
- ldr $rk8q, [$cc, #128] @ load rk8
+ ld1 {$rk4s}, [$cc], #16 @ load rk4
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
- ldr $rk11q, [$cc, #176] @ load rk11
+ ld1 {$rk5s}, [$cc], #16 @ load rk5
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+#ifndef __AARCH64EB__
ext $h4b, $h4b, $h4b, #8
-
+#endif
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+#ifndef __AARCH64EB__
ext $h2b, $h2b, $h2b, #8
-
+#endif
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+#ifndef __AARCH64EB__
ext $h3b, $h3b, $h3b, #8
-
+#endif
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
- ldp $rk12_l, $rk12_h, [$cc, #192] @ load rk12
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+#ifndef __AARCH64EB__
ext $h1b, $h1b, $h1b, #8
-
+#endif
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
- ldr $rk10q, [$cc, #160] @ load rk10
+ ld1 {$rk6s}, [$cc], #16 @ load rk6
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 3
- ldr $rk9q, [$cc, #144] @ load rk9
+ ld1 {$rk7s}, [$cc], #16 @ load rk7
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
- ldr $rk7q, [$cc, #112] @ load rk7
+ ld1 {$rk8s}, [$cc], #16 @ load rk8
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
- ldr $rk4q, [$cc, #64] @ load rk4
+ ld1 {$rk9s}, [$cc], #16 @ load rk9
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 3
ld1 { $acc_lb}, [$current_tag]
ext $acc_lb, $acc_lb, $acc_lb, #8
rev64 $acc_lb, $acc_lb
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 3
add $rctr32w, $rctr32w, #1 @ CTR block 3
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 3
trn1 $acc_h.2d, $h3.2d, $h4.2d @ h4h | h3h
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 4
- ldr $rk5q, [$cc, #80] @ load rk5
+ ld1 {$rk10s}, [$cc], #16 @ load rk10
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 4
trn2 $h34k.2d, $h3.2d, $h4.2d @ h4l | h3l
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 4
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 4
trn2 $h12k.2d, $h1.2d, $h2.2d @ h2l | h1l
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 5
- ldr $rk6q, [$cc, #96] @ load rk6
+ ld1 {$rk11s}, [$cc], #16 @ load rk11
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 5
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 5
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 5
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 6
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 6
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 6
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 7
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 7
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 7
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 6
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 8
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 8
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 7
aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 9
aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 9
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 8
sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 8
and $main_end_input_ptr, $main_end_input_ptr, #0xffffffffffffffc0 @ number of bytes to be processed in main loop (at least 1 byte must be handled by tail)
aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 10
add $main_end_input_ptr, $main_end_input_ptr, $input_ptr
aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 9
cmp $input_ptr, $main_end_input_ptr @ check if we have <= 4 blocks
aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 9
trn1 $t0.2d, $h1.2d, $h2.2d @ h2h | h1h
aese $ctr3b, $rk11 @ AES block 3 - round 11
aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 10
aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 10
aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 10
eor $h12k.16b, $h12k.16b, $t0.16b @ h2k | h1k
aese $ctr2b, $rk11 @ AES block 2 - round 11
aese $ctr1b, $rk11 @ AES block 1 - round 11
eor $h34k.16b, $h34k.16b, $acc_h.16b @ h4k | h3k
aese $ctr0b, $rk11 @ AES block 0 - round 11
b.ge .L192_dec_tail @ handle tail
- ldr $res1q, [$input_ptr, #16] @ AES block 1 - load ciphertext
-
- ldr $res0q, [$input_ptr, #0] @ AES block 0 - load ciphertext
+ ld1 {$res0b, $res1b}, [$input_ptr], #32 @ AES block 0,1 - load ciphertext
eor $ctr1b, $res1b, $ctr1b @ AES block 1 - result
eor $ctr0b, $res0b, $ctr0b @ AES block 0 - result
rev $ctr32w, $rctr32w @ CTR block 4
- ldr $res3q, [$input_ptr, #48] @ AES block 3 - load ciphertext
-
- ldr $res2q, [$input_ptr, #32] @ AES block 2 - load ciphertext
+ ld1 {$res2b, $res3b}, [$input_ptr], #32 @ AES block 2,3 - load ciphertext
mov $output_l1, $ctr1.d[0] @ AES block 1 - mov low
mov $output_h1, $ctr1.d[1] @ AES block 1 - mov high
mov $output_l0, $ctr0.d[0] @ AES block 0 - mov low
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4
add $rctr32w, $rctr32w, #1 @ CTR block 4
mov $output_h0, $ctr0.d[1] @ AES block 0 - mov high
rev64 $res0b, $res0b @ GHASH block 0
- add $input_ptr, $input_ptr, #64 @ AES input_ptr update
fmov $ctr0d, $ctr96_b64x @ CTR block 4
rev64 $res1b, $res1b @ GHASH block 1
cmp $input_ptr, $main_end_input_ptr @ check if we have <= 8 blocks
eor $output_l1, $output_l1, $rk12_l @ AES block 1 - round 12 low
+#ifdef __AARCH64EB__
+ rev $output_l1, $output_l1
+#endif
fmov $ctr0.d[1], $ctr32x @ CTR block 4
rev $ctr32w, $rctr32w @ CTR block 5
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 5
fmov $ctr1d, $ctr96_b64x @ CTR block 5
eor $output_h1, $output_h1, $rk12_h @ AES block 1 - round 12 high
-
+#ifdef __AARCH64EB__
+ rev $output_h1, $output_h1
+#endif
add $rctr32w, $rctr32w, #1 @ CTR block 5
fmov $ctr1.d[1], $ctr32x @ CTR block 5
eor $output_l0, $output_l0, $rk12_l @ AES block 0 - round 12 low
-
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
rev $ctr32w, $rctr32w @ CTR block 6
eor $output_h0, $output_h0, $rk12_h @ AES block 0 - round 12 high
-
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES block 0 - store result
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 6
stp $output_l1, $output_h1, [$output_ptr], #16 @ AES block 1 - store result
add $rctr32w, $rctr32w, #1 @ CTR block 6
eor $ctr2b, $res2b, $ctr2b @ AES block 2 - result
b.ge .L192_dec_prepretail @ do prepretail
.L192_dec_main_loop: @ main loop start
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
mov $output_l2, $ctr2.d[0] @ AES block 4k+2 - mov low
mov $output_h2, $ctr2.d[1] @ AES block 4k+2 - mov high
eor $ctr3b, $res3b, $ctr3b @ AES block 4k+3 - result
rev64 $res3b, $res3b @ GHASH block 4k+3
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
fmov $ctr2d, $ctr96_b64x @ CTR block 4k+6
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
eor $res0b, $res0b, $acc_lb @ PRE 1
pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
fmov $ctr2.d[1], $ctr32x @ CTR block 4k+6
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
mov $output_h3, $ctr3.d[1] @ AES block 4k+3 - mov high
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
mov $output_l3, $ctr3.d[0] @ AES block 4k+3 - mov low
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
fmov $ctr3d, $ctr96_b64x @ CTR block 4k+7
mov $t0d, $res0.d[1] @ GHASH block 4k - mid
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
rev $ctr32w, $rctr32w @ CTR block 4k+7
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+7
fmov $ctr3.d[1], $ctr32x @ CTR block 4k+7
eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
eor $output_h2, $output_h2, $rk12_h @ AES block 4k+2 - round 12 high
-
+#ifdef __AARCH64EB__
+ rev $output_h2, $output_h2
+#endif
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
rev64 $res2b, $res2b @ GHASH block 4k+2
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
eor $output_l2, $output_l2, $rk12_l @ AES block 4k+2 - round 12 low
-
+#ifdef __AARCH64EB__
+ rev $output_l2, $output_l2
+#endif
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
movi $mod_constant.8b, #0xc2
pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
- ldr $res2q, [$input_ptr, #32] @ AES block 4k+6 - load ciphertext
+ ld1 {$res0b}, [$input_ptr], #16 @ AES block 4k+4 - load ciphertext
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
- ldr $res3q, [$input_ptr, #48] @ AES block 4k+7 - load ciphertext
+ ld1 {$res1b}, [$input_ptr], #16 @ AES block 4k+5 - load ciphertext
eor $output_l3, $output_l3, $rk12_l @ AES block 4k+3 - round 12 low
-
+#ifdef __AARCH64EB__
+ rev $output_l3, $output_l3
+#endif
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
aese $ctr0b, $rk11 @ AES block 4k+4 - round 11
add $rctr32w, $rctr32w, #1 @ CTR block 4k+7
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
- ldr $res0q, [$input_ptr, #0] @ AES block 4k+4 - load ciphertext
+ ld1 {$res2b}, [$input_ptr], #16 @ AES block 4k+6 - load ciphertext
aese $ctr1b, $rk11 @ AES block 4k+5 - round 11
- ldr $res1q, [$input_ptr, #16] @ AES block 4k+5 - load ciphertext
+ ld1 {$res3b}, [$input_ptr], #16 @ AES block 4k+7 - load ciphertext
rev $ctr32w, $rctr32w @ CTR block 4k+8
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
stp $output_l2, $output_h2, [$output_ptr], #16 @ AES block 4k+2 - store result
aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
- add $input_ptr, $input_ptr, #64 @ AES input_ptr update
cmp $input_ptr, $main_end_input_ptr @ LOOP CONTROL
eor $ctr0b, $res0b, $ctr0b @ AES block 4k+4 - result
eor $output_h3, $output_h3, $rk12_h @ AES block 4k+3 - round 12 high
+#ifdef __AARCH64EB__
+ rev $output_h3, $output_h3
+#endif
eor $ctr1b, $res1b, $ctr1b @ AES block 4k+5 - result
aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+8
aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
mov $output_l1, $ctr1.d[0] @ AES block 4k+5 - mov low
mov $output_l0, $ctr0.d[0] @ AES block 4k+4 - mov low
stp $output_l3, $output_h3, [$output_ptr], #16 @ AES block 4k+3 - store result
rev64 $res1b, $res1b @ GHASH block 4k+5
aese $ctr2b, $rk11 @ AES block 4k+6 - round 11
mov $output_h0, $ctr0.d[1] @ AES block 4k+4 - mov high
aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
mov $output_h1, $ctr1.d[1] @ AES block 4k+5 - mov high
fmov $ctr0d, $ctr96_b64x @ CTR block 4k+8
add $rctr32w, $rctr32w, #1 @ CTR block 4k+8
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
eor $ctr2b, $res2b, $ctr2b @ AES block 4k+6 - result
fmov $ctr0.d[1], $ctr32x @ CTR block 4k+8
rev $ctr32w, $rctr32w @ CTR block 4k+9
eor $output_l0, $output_l0, $rk12_l @ AES block 4k+4 - round 12 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+9
eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
fmov $ctr1d, $ctr96_b64x @ CTR block 4k+9
add $rctr32w, $rctr32w, #1 @ CTR block 4k+9
eor $output_l1, $output_l1, $rk12_l @ AES block 4k+5 - round 12 low
-
+#ifdef __AARCH64EB__
+ rev $output_l1, $output_l1
+#endif
fmov $ctr1.d[1], $ctr32x @ CTR block 4k+9
rev $ctr32w, $rctr32w @ CTR block 4k+10
eor $output_h1, $output_h1, $rk12_h @ AES block 4k+5 - round 12 high
-
+#ifdef __AARCH64EB__
+ rev $output_h1, $output_h1
+#endif
eor $output_h0, $output_h0, $rk12_h @ AES block 4k+4 - round 12 high
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES block 4k+4 - store result
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
add $rctr32w, $rctr32w, #1 @ CTR block 4k+10
rev64 $res0b, $res0b @ GHASH block 4k+4
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+10
aese $ctr3b, $rk11 @ AES block 4k+7 - round 11
stp $output_l1, $output_h1, [$output_ptr], #16 @ AES block 4k+5 - store result
b.lt .L192_dec_main_loop
.L192_dec_prepretail: @ PREPRETAIL
mov $output_h2, $ctr2.d[1] @ AES block 4k+2 - mov high
ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
eor $ctr3b, $res3b, $ctr3b @ AES block 4k+3 - result
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
mov $output_l2, $ctr2.d[0] @ AES block 4k+2 - mov low
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
eor $res0b, $res0b, $acc_lb @ PRE 1
fmov $ctr2d, $ctr96_b64x @ CTR block 4k+6
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
mov $output_l3, $ctr3.d[0] @ AES block 4k+3 - mov low
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
mov $output_h3, $ctr3.d[1] @ AES block 4k+3 - mov high
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
mov $t0d, $res0.d[1] @ GHASH block 4k - mid
fmov $ctr3d, $ctr96_b64x @ CTR block 4k+7
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
rev64 $res2b, $res2b @ GHASH block 4k+2
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
fmov $ctr2.d[1], $ctr32x @ CTR block 4k+6
rev $ctr32w, $rctr32w @ CTR block 4k+7
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+7
eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
eor $output_h3, $output_h3, $rk12_h @ AES block 4k+3 - round 12 high
+#ifdef __AARCH64EB__
+ rev $output_h3, $output_h3
+#endif
fmov $ctr3.d[1], $ctr32x @ CTR block 4k+7
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
eor $output_l2, $output_l2, $rk12_l @ AES block 4k+2 - round 12 low
-
+#ifdef __AARCH64EB__
+ rev $output_l2, $output_l2
+#endif
pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
eor $output_h2, $output_h2, $rk12_h @ AES block 4k+2 - round 12 high
+#ifdef __AARCH64EB__
+ rev $output_h2, $output_h2
+#endif
eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
eor $output_l3, $output_l3, $rk12_l @ AES block 4k+3 - round 12 low
+#ifdef __AARCH64EB__
+ rev $output_l3, $output_l3
+#endif
stp $output_l2, $output_h2, [$output_ptr], #16 @ AES block 4k+2 - store result
rev64 $res3b, $res3b @ GHASH block 4k+3
stp $output_l3, $output_h3, [$output_ptr], #16 @ AES block 4k+3 - store result
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
add $rctr32w, $rctr32w, #1 @ CTR block 4k+7
pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
movi $mod_constant.8b, #0xc2
pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
aese $ctr0b, $rk11
eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
aese $ctr2b, $rk11
aese $ctr1b, $rk11
aese $ctr3b, $rk11
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
.L192_dec_tail: @ TAIL
sub $main_end_input_ptr, $end_input_ptr, $input_ptr @ main_end_input_ptr is number of bytes left to process
ld1 { $res1b}, [$input_ptr], #16 @ AES block 4k+4 - load ciphertext
eor $ctr0b, $res1b, $ctr0b @ AES block 4k+4 - result
mov $output_h0, $ctr0.d[1] @ AES block 4k+4 - mov high
mov $output_l0, $ctr0.d[0] @ AES block 4k+4 - mov low
ext $t0.16b, $acc_lb, $acc_lb, #8 @ prepare final partial tag
cmp $main_end_input_ptr, #48
eor $output_h0, $output_h0, $rk12_h @ AES block 4k+4 - round 12 high
-
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
eor $output_l0, $output_l0, $rk12_l @ AES block 4k+4 - round 12 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
b.gt .L192_dec_blocks_more_than_3
movi $acc_l.8b, #0
movi $acc_h.8b, #0
mov $ctr3b, $ctr2b
mov $ctr2b, $ctr1b
sub $rctr32w, $rctr32w, #1
movi $acc_m.8b, #0
cmp $main_end_input_ptr, #32
b.gt .L192_dec_blocks_more_than_2
mov $ctr3b, $ctr1b
cmp $main_end_input_ptr, #16
sub $rctr32w, $rctr32w, #1
b.gt .L192_dec_blocks_more_than_1
sub $rctr32w, $rctr32w, #1
b .L192_dec_blocks_less_than_1
.L192_dec_blocks_more_than_3: @ blocks left > 3
rev64 $res0b, $res1b @ GHASH final-3 block
ld1 { $res1b}, [$input_ptr], #16 @ AES final-2 block - load ciphertext
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-3 block - store result
eor $res0b, $res0b, $t0.16b @ feed in partial tag
eor $ctr0b, $res1b, $ctr1b @ AES final-2 block - result
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH final-3 block - low
mov $output_l0, $ctr0.d[0] @ AES final-2 block - mov low
mov $rk4d, $res0.d[1] @ GHASH final-3 block - mid
mov $output_h0, $ctr0.d[1] @ AES final-2 block - mov high
mov $acc_md, $h34k.d[1] @ GHASH final-3 block - mid
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-3 block - mid
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH final-3 block - high
eor $output_l0, $output_l0, $rk12_l @ AES final-2 block - round 12 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
movi $t0.8b, #0 @ suppress further partial tag feed in
pmull $acc_m.1q, $rk4v.1d, $acc_m.1d @ GHASH final-3 block - mid
eor $output_h0, $output_h0, $rk12_h @ AES final-2 block - round 12 high
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
.L192_dec_blocks_more_than_2: @ blocks left > 2
rev64 $res0b, $res1b @ GHASH final-2 block
ld1 { $res1b}, [$input_ptr], #16 @ AES final-1 block - load ciphertext
eor $res0b, $res0b, $t0.16b @ feed in partial tag
movi $t0.8b, #0 @ suppress further partial tag feed in
eor $ctr0b, $res1b, $ctr2b @ AES final-1 block - result
mov $rk4d, $res0.d[1] @ GHASH final-2 block - mid
pmull $rk3q1, $res0.1d, $h3.1d @ GHASH final-2 block - low
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-2 block - store result
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-2 block - mid
mov $output_h0, $ctr0.d[1] @ AES final-1 block - mov high
eor $acc_lb, $acc_lb, $rk3 @ GHASH final-2 block - low
mov $output_l0, $ctr0.d[0] @ AES final-1 block - mov low
pmull2 $rk2q1, $res0.2d, $h3.2d @ GHASH final-2 block - high
pmull $rk4v.1q, $rk4v.1d, $h34k.1d @ GHASH final-2 block - mid
eor $acc_hb, $acc_hb, $rk2 @ GHASH final-2 block - high
eor $output_h0, $output_h0, $rk12_h @ AES final-1 block - round 12 high
-
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
eor $output_l0, $output_l0, $rk12_l @ AES final-1 block - round 12 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-2 block - mid
.L192_dec_blocks_more_than_1: @ blocks left > 1
rev64 $res0b, $res1b @ GHASH final-1 block
eor $res0b, $res0b, $t0.16b @ feed in partial tag
ld1 { $res1b}, [$input_ptr], #16 @ AES final block - load ciphertext
mov $rk4d, $res0.d[1] @ GHASH final-1 block - mid
pmull2 $rk2q1, $res0.2d, $h2.2d @ GHASH final-1 block - high
eor $ctr0b, $res1b, $ctr3b @ AES final block - result
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-1 block - store result
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-1 block - mid
eor $acc_hb, $acc_hb, $rk2 @ GHASH final-1 block - high
pmull $rk3q1, $res0.1d, $h2.1d @ GHASH final-1 block - low
mov $output_h0, $ctr0.d[1] @ AES final block - mov high
ins $rk4v.d[1], $rk4v.d[0] @ GHASH final-1 block - mid
mov $output_l0, $ctr0.d[0] @ AES final block - mov low
pmull2 $rk4v.1q, $rk4v.2d, $h12k.2d @ GHASH final-1 block - mid
movi $t0.8b, #0 @ suppress further partial tag feed in
eor $acc_lb, $acc_lb, $rk3 @ GHASH final-1 block - low
eor $output_h0, $output_h0, $rk12_h @ AES final block - round 12 high
-
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
eor $output_l0, $output_l0, $rk12_l @ AES final block - round 12 low
-
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-1 block - mid
.L192_dec_blocks_less_than_1: @ blocks left <= 1
mvn $rk12_l, xzr @ rk12_l = 0xffffffffffffffff
ldp $end_input_ptr, $main_end_input_ptr, [$output_ptr] @ load existing bytes we need to not overwrite
and $bit_length, $bit_length, #127 @ bit_length %= 128
sub $bit_length, $bit_length, #128 @ bit_length -= 128
neg $bit_length, $bit_length @ bit_length = 128 - #bits in input (in range [1,128])
and $bit_length, $bit_length, #127 @ bit_length %= 128
mvn $rk12_h, xzr @ rk12_h = 0xffffffffffffffff
lsr $rk12_h, $rk12_h, $bit_length @ rk12_h is mask for top 64b of last block
cmp $bit_length, #64
csel $ctr32x, $rk12_l, $rk12_h, lt
csel $ctr96_b64x, $rk12_h, xzr, lt
fmov $ctr0d, $ctr32x @ ctr0b is mask for last block
and $output_l0, $output_l0, $ctr32x
bic $end_input_ptr, $end_input_ptr, $ctr32x @ mask out low existing bytes
orr $output_l0, $output_l0, $end_input_ptr
mov $ctr0.d[1], $ctr96_b64x
-
+#ifndef __AARCH64EB__
rev $ctr32w, $rctr32w
+#else
+ mov $ctr32w, $rctr32w
+#endif
and $res1b, $res1b, $ctr0b @ possibly partial last block has zeroes in highest bits
str $ctr32w, [$counter, #12] @ store the updated counter
rev64 $res0b, $res1b @ GHASH final block
eor $res0b, $res0b, $t0.16b @ feed in partial tag
bic $main_end_input_ptr, $main_end_input_ptr, $ctr96_b64x @ mask out high existing bytes
and $output_h0, $output_h0, $ctr96_b64x
pmull2 $rk2q1, $res0.2d, $h1.2d @ GHASH final block - high
mov $t0d, $res0.d[1] @ GHASH final block - mid
pmull $rk3q1, $res0.1d, $h1.1d @ GHASH final block - low
eor $t0.8b, $t0.8b, $res0.8b @ GHASH final block - mid
eor $acc_hb, $acc_hb, $rk2 @ GHASH final block - high
pmull $t0.1q, $t0.1d, $h12k.1d @ GHASH final block - mid
eor $acc_lb, $acc_lb, $rk3 @ GHASH final block - low
eor $acc_mb, $acc_mb, $t0.16b @ GHASH final block - mid
movi $mod_constant.8b, #0xc2
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
orr $output_h0, $output_h0, $main_end_input_ptr
stp $output_l0, $output_h0, [$output_ptr]
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
ext $acc_lb, $acc_lb, $acc_lb, #8
rev64 $acc_lb, $acc_lb
mov x0, $len
st1 { $acc_l.16b }, [$current_tag]
ldp x21, x22, [sp, #16]
ldp x23, x24, [sp, #32]
ldp d8, d9, [sp, #48]
ldp d10, d11, [sp, #64]
ldp d12, d13, [sp, #80]
ldp d14, d15, [sp, #96]
ldp x19, x20, [sp], #112
ret
.L192_dec_ret:
mov w0, #0x0
ret
.size aes_gcm_dec_192_kernel,.-aes_gcm_dec_192_kernel
___
}
{
my ($end_input_ptr,$main_end_input_ptr,$input_l0,$input_h0)=map("x$_",(4..7));
my ($input_l1,$input_h1,$input_l2,$input_h2,$input_l3,$input_h3)=map("x$_",(19..24));
my ($output_l1,$output_h1,$output_l2,$output_h2,$output_l3,$output_h3)=map("x$_",(19..24));
my ($output_l0,$output_h0)=map("x$_",(6..7));
my $ctr32w="w9";
my ($ctr32x,$ctr96_b64x,$ctr96_t32x,$rctr32x,$rk14_l,$rk14_h,$len)=map("x$_",(9..15));
my ($ctr96_t32w,$rctr32w)=map("w$_",(11..12));
my ($ctr0b,$ctr1b,$ctr2b,$ctr3b,$res0b,$res1b,$res2b,$res3b)=map("v$_.16b",(0..7));
my ($ctr0,$ctr1,$ctr2,$ctr3,$res0,$res1,$res2,$res3)=map("v$_",(0..7));
my ($ctr0d,$ctr1d,$ctr2d,$ctr3d,$res0d,$res1d,$res2d,$res3d)=map("d$_",(0..7));
my ($res0q,$res1q,$res2q,$res3q)=map("q$_",(4..7));
my ($acc_hb,$acc_mb,$acc_lb)=map("v$_.16b",(9..11));
my ($acc_h,$acc_m,$acc_l)=map("v$_",(9..11));
my ($acc_hd,$acc_md,$acc_ld)=map("d$_",(9..11));
my ($h1,$h2,$h3,$h4,$h12k,$h34k)=map("v$_",(12..17));
my ($h1q,$h2q,$h3q,$h4q)=map("q$_",(12..15));
my ($h1b,$h2b,$h3b,$h4b)=map("v$_.16b",(12..15));
my $t0="v8";
my $t0d="d8";
my $t1="v4";
my $t1d="d4";
my $t2="v8";
my $t2d="d8";
my $t3="v4";
my $t3d="d4";
my $t4="v4";
my $t4d="d4";
my $t5="v5";
my $t5d="d5";
my $t6="v8";
my $t6d="d8";
my $t7="v5";
my $t7d="d5";
my $t8="v6";
my $t8d="d6";
my $t9="v4";
my $t9d="d4";
my ($ctr_t0,$ctr_t1,$ctr_t2,$ctr_t3)=map("v$_",(4..7));
my ($ctr_t0d,$ctr_t1d,$ctr_t2d,$ctr_t3d)=map("d$_",(4..7));
my ($ctr_t0b,$ctr_t1b,$ctr_t2b,$ctr_t3b)=map("v$_.16b",(4..7));
my $mod_constantd="d8";
my $mod_constant="v8";
my $mod_t="v7";
my ($rk0,$rk1,$rk2,$rk3,$rk4,$rk5,$rk6,$rk7,$rk8,$rk9,$rk10,$rk11,$rk12,$rk13)=map("v$_.16b",(18..31));
+my ($rk0s,$rk1s,$rk2s,$rk3s,$rk4s,$rk5s,$rk6s,$rk7s,$rk8s,$rk9s,$rk10s,$rk11s,$rk12s,$rk13s)=map("v$_.4s",(18..31));
my ($rk0q,$rk1q,$rk2q,$rk3q,$rk4q,$rk5q,$rk6q,$rk7q,$rk8q,$rk9q,$rk10q,$rk11q,$rk12q,$rk13q)=map("q$_",(18..31));
my $rk2q1="v20.1q";
my $rk3q1="v21.1q";
my $rk4v="v22";
my $rk4d="d22";
#########################################################################################
# size_t aes_gcm_enc_256_kernel(const unsigned char *in,
# size_t len,
# unsigned char *out,
# const void *key,
# unsigned char ivec[16],
# u64 *Xi);
#
$code.=<<___;
.global aes_gcm_enc_256_kernel
.type aes_gcm_enc_256_kernel,%function
.align 4
aes_gcm_enc_256_kernel:
cbz x1, .L256_enc_ret
stp x19, x20, [sp, #-112]!
mov x16, x4
mov x8, x5
stp x21, x22, [sp, #16]
stp x23, x24, [sp, #32]
stp d8, d9, [sp, #48]
stp d10, d11, [sp, #64]
stp d12, d13, [sp, #80]
stp d14, d15, [sp, #96]
add $end_input_ptr, $input_ptr, $bit_length, lsr #3 @ end_input_ptr
lsr $main_end_input_ptr, $bit_length, #3 @ byte_len
mov $len, $main_end_input_ptr
ldp $ctr96_b64x, $ctr96_t32x, [$counter] @ ctr96_b64, ctr96_t32
-
+#ifdef __AARCH64EB__
+ rev $ctr96_b64x, $ctr96_b64x
+ rev $ctr96_t32x, $ctr96_t32x
+#endif
+ ldp $rk14_l, $rk14_h, [$cc, #224] @ load rk14
+#ifdef __AARCH64EB__
+ ror $rk14_l, $rk14_l, #32
+ ror $rk14_h, $rk14_h, #32
+#endif
ld1 { $ctr0b}, [$counter] @ special case vector load initial counter so we can start first AES block as quickly as possible
sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
- ldr $rk0q, [$cc, #0] @ load rk0
+ ld1 {$rk0s}, [$cc], #16 @ load rk0
and $main_end_input_ptr, $main_end_input_ptr, #0xffffffffffffffc0 @ number of bytes to be processed in main loop (at least 1 byte must be handled by tail)
- ldr $rk7q, [$cc, #112] @ load rk7
+ ld1 {$rk1s}, [$cc], #16 @ load rk1
add $main_end_input_ptr, $main_end_input_ptr, $input_ptr
lsr $rctr32x, $ctr96_t32x, #32
fmov $ctr2d, $ctr96_b64x @ CTR block 2
orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
rev $rctr32w, $rctr32w @ rev_ctr32
cmp $input_ptr, $main_end_input_ptr @ check if we have <= 4 blocks
fmov $ctr1d, $ctr96_b64x @ CTR block 1
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
add $rctr32w, $rctr32w, #1 @ increment rev_ctr32
rev $ctr32w, $rctr32w @ CTR block 1
fmov $ctr3d, $ctr96_b64x @ CTR block 3
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 1
add $rctr32w, $rctr32w, #1 @ CTR block 1
- ldr $rk1q, [$cc, #16] @ load rk1
+ ld1 {$rk2s}, [$cc], #16 @ load rk2
fmov $ctr1.d[1], $ctr32x @ CTR block 1
rev $ctr32w, $rctr32w @ CTR block 2
add $rctr32w, $rctr32w, #1 @ CTR block 2
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 2
- ldr $rk2q, [$cc, #32] @ load rk2
+ ld1 {$rk3s}, [$cc], #16 @ load rk3
fmov $ctr2.d[1], $ctr32x @ CTR block 2
rev $ctr32w, $rctr32w @ CTR block 3
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 3
fmov $ctr3.d[1], $ctr32x @ CTR block 3
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
- ldr $rk3q, [$cc, #48] @ load rk3
+ ld1 {$rk4s}, [$cc], #16 @ load rk4
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
- ldr $rk6q, [$cc, #96] @ load rk6
+ ld1 {$rk5s}, [$cc], #16 @ load rk5
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
- ldr $rk5q, [$cc, #80] @ load rk5
+ ld1 {$rk6s}, [$cc], #16 @ load rk6
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+#ifndef __AARCH64EB__
ext $h3b, $h3b, $h3b, #8
-
+#endif
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
- ldr $rk13q, [$cc, #208] @ load rk13
+ ld1 {$rk7s}, [$cc], #16 @ load rk7
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
- ldr $rk4q, [$cc, #64] @ load rk4
+ ld1 {$rk8s}, [$cc], #16 @ load rk8
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+#ifndef __AARCH64EB__
ext $h2b, $h2b, $h2b, #8
-
+#endif
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
- ldr $rk12q, [$cc, #192] @ load rk12
+ ld1 {$rk9s}, [$cc], #16 @ load rk9
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+#ifndef __AARCH64EB__
ext $h4b, $h4b, $h4b, #8
-
+#endif
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 3
- ldr $rk11q, [$cc, #176] @ load rk11
+ ld1 {$rk10s}, [$cc], #16 @ load rk10
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
- ldr $rk8q, [$cc, #128] @ load rk8
+ ld1 {$rk11s}, [$cc], #16 @ load rk11
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 3
add $rctr32w, $rctr32w, #1 @ CTR block 3
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 3
- ldp $rk14_l, $rk14_h, [$cc, #224] @ load rk14
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 3
ld1 { $acc_lb}, [$current_tag]
ext $acc_lb, $acc_lb, $acc_lb, #8
rev64 $acc_lb, $acc_lb
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 4
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 4
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 4
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 4
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 5
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 5
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 5
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 5
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 6
trn2 $h34k.2d, $h3.2d, $h4.2d @ h4l | h3l
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 6
- ldr $rk9q, [$cc, #144] @ load rk9
+ ld1 {$rk12s}, [$cc], #16 @ load rk12
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 6
ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+#ifndef __AARCH64EB__
ext $h1b, $h1b, $h1b, #8
-
+#endif
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 6
- ldr $rk10q, [$cc, #160] @ load rk10
+ ld1 {$rk13s}, [$cc], #16 @ load rk13
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 7
trn1 $acc_h.2d, $h3.2d, $h4.2d @ h4h | h3h
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 7
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 7
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 7
trn2 $h12k.2d, $h1.2d, $h2.2d @ h2l | h1l
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 8
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 8
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 8
aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 9
aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 9
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 8
aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 10
aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 9
aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 9
aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 10
aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 10
aese $ctr1b, $rk11 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 11
aese $ctr2b, $rk11 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 11
aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 10
aese $ctr1b, $rk12 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 12
aese $ctr2b, $rk12 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 12
aese $ctr0b, $rk11 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 11
eor $h34k.16b, $h34k.16b, $acc_h.16b @ h4k | h3k
aese $ctr3b, $rk11 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 11
aese $ctr2b, $rk13 @ AES block 2 - round 13
trn1 $t0.2d, $h1.2d, $h2.2d @ h2h | h1h
aese $ctr0b, $rk12 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 12
aese $ctr3b, $rk12 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 12
aese $ctr1b, $rk13 @ AES block 1 - round 13
aese $ctr0b, $rk13 @ AES block 0 - round 13
aese $ctr3b, $rk13 @ AES block 3 - round 13
eor $h12k.16b, $h12k.16b, $t0.16b @ h2k | h1k
b.ge .L256_enc_tail @ handle tail
ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 1 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l1, $input_l1
+ rev $input_h1, $input_h1
+#endif
rev $ctr32w, $rctr32w @ CTR block 4
ldp $input_l0, $input_h0, [$input_ptr, #0] @ AES block 0 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 3 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l3, $input_l3
+ rev $input_h3, $input_h3
+#endif
ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 2 - load plaintext
+#ifdef __AARCH64EB__
+ rev $input_l2, $input_l2
+ rev $input_h2, $input_h2
+#endif
add $input_ptr, $input_ptr, #64 @ AES input_ptr update
eor $input_l1, $input_l1, $rk14_l @ AES block 1 - round 14 low
eor $input_h1, $input_h1, $rk14_h @ AES block 1 - round 14 high
fmov $ctr_t1d, $input_l1 @ AES block 1 - mov low
eor $input_l0, $input_l0, $rk14_l @ AES block 0 - round 14 low
eor $input_h0, $input_h0, $rk14_h @ AES block 0 - round 14 high
eor $input_h3, $input_h3, $rk14_h @ AES block 3 - round 14 high
fmov $ctr_t0d, $input_l0 @ AES block 0 - mov low
cmp $input_ptr, $main_end_input_ptr @ check if we have <= 8 blocks
fmov $ctr_t0.d[1], $input_h0 @ AES block 0 - mov high
eor $input_l3, $input_l3, $rk14_l @ AES block 3 - round 14 low
eor $input_l2, $input_l2, $rk14_l @ AES block 2 - round 14 low
fmov $ctr_t1.d[1], $input_h1 @ AES block 1 - mov high
fmov $ctr_t2d, $input_l2 @ AES block 2 - mov low
add $rctr32w, $rctr32w, #1 @ CTR block 4
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4
fmov $ctr_t3d, $input_l3 @ AES block 3 - mov low
eor $input_h2, $input_h2, $rk14_h @ AES block 2 - round 14 high
fmov $ctr_t2.d[1], $input_h2 @ AES block 2 - mov high
eor $res0b, $ctr_t0b, $ctr0b @ AES block 0 - result
fmov $ctr0d, $ctr96_b64x @ CTR block 4
fmov $ctr0.d[1], $ctr32x @ CTR block 4
rev $ctr32w, $rctr32w @ CTR block 5
add $rctr32w, $rctr32w, #1 @ CTR block 5
eor $res1b, $ctr_t1b, $ctr1b @ AES block 1 - result
fmov $ctr1d, $ctr96_b64x @ CTR block 5
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 5
fmov $ctr1.d[1], $ctr32x @ CTR block 5
rev $ctr32w, $rctr32w @ CTR block 6
st1 { $res0b}, [$output_ptr], #16 @ AES block 0 - store result
fmov $ctr_t3.d[1], $input_h3 @ AES block 3 - mov high
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 6
eor $res2b, $ctr_t2b, $ctr2b @ AES block 2 - result
st1 { $res1b}, [$output_ptr], #16 @ AES block 1 - store result
add $rctr32w, $rctr32w, #1 @ CTR block 6
fmov $ctr2d, $ctr96_b64x @ CTR block 6
fmov $ctr2.d[1], $ctr32x @ CTR block 6
st1 { $res2b}, [$output_ptr], #16 @ AES block 2 - store result
rev $ctr32w, $rctr32w @ CTR block 7
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 7
eor $res3b, $ctr_t3b, $ctr3b @ AES block 3 - result
st1 { $res3b}, [$output_ptr], #16 @ AES block 3 - store result
b.ge L256_enc_prepretail @ do prepretail
.L256_enc_main_loop: @ main loop start
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
rev64 $res0b, $res0b @ GHASH block 4k (only t0 is free)
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
fmov $ctr3d, $ctr96_b64x @ CTR block 4k+3
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
fmov $ctr3.d[1], $ctr32x @ CTR block 4k+3
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
ldp $input_l3, $input_h3, [$input_ptr, #48] @ AES block 4k+7 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l3, $input_l3
+ rev $input_h3, $input_h3
+#endif
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
ldp $input_l2, $input_h2, [$input_ptr, #32] @ AES block 4k+6 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l2, $input_l2
+ rev $input_h2, $input_h2
+#endif
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
eor $res0b, $res0b, $acc_lb @ PRE 1
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
eor $input_l3, $input_l3, $rk14_l @ AES block 4k+7 - round 14 low
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
eor $input_h2, $input_h2, $rk14_h @ AES block 4k+6 - round 14 high
mov $t0d, $res0.d[1] @ GHASH block 4k - mid
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
rev64 $res1b, $res1b @ GHASH block 4k+1 (t0 and t1 free)
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
rev64 $res3b, $res3b @ GHASH block 4k+3 (t0, t1, t2 and t3 free)
pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
rev64 $res2b, $res2b @ GHASH block 4k+2 (t0, t1, and t2 free)
pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
ldp $input_l1, $input_h1, [$input_ptr, #16] @ AES block 4k+5 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l1, $input_l1
+ rev $input_h1, $input_h1
+#endif
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
eor $input_l1, $input_l1, $rk14_l @ AES block 4k+5 - round 14 low
aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
eor $input_l2, $input_l2, $rk14_l @ AES block 4k+6 - round 14 low
aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
movi $mod_constant.8b, #0xc2
pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
fmov $ctr_t1d, $input_l1 @ AES block 4k+5 - mov low
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
ldp $input_l0, $input_h0, [$input_ptr, #0] @ AES block 4k+4 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
add $rctr32w, $rctr32w, #1 @ CTR block 4k+3
aese $ctr0b, $rk11 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 11
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
aese $ctr1b, $rk11 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 11
add $input_ptr, $input_ptr, #64 @ AES input_ptr update
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
rev $ctr32w, $rctr32w @ CTR block 4k+8
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
eor $input_l0, $input_l0, $rk14_l @ AES block 4k+4 - round 14 low
aese $ctr1b, $rk12 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 12
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
eor $input_h0, $input_h0, $rk14_h @ AES block 4k+4 - round 14 high
fmov $ctr_t0d, $input_l0 @ AES block 4k+4 - mov low
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+8
eor $mod_t.16b, $acc_hb, $mod_t.16b @ MODULO - fold into mid
aese $ctr0b, $rk12 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 12
eor $input_h1, $input_h1, $rk14_h @ AES block 4k+5 - round 14 high
aese $ctr2b, $rk11 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 11
eor $input_h3, $input_h3, $rk14_h @ AES block 4k+7 - round 14 high
aese $ctr3b, $rk11 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 11
add $rctr32w, $rctr32w, #1 @ CTR block 4k+8
aese $ctr0b, $rk13 @ AES block 4k+4 - round 13
fmov $ctr_t0.d[1], $input_h0 @ AES block 4k+4 - mov high
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
aese $ctr2b, $rk12 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 12
fmov $ctr_t3d, $input_l3 @ AES block 4k+7 - mov low
aese $ctr1b, $rk13 @ AES block 4k+5 - round 13
fmov $ctr_t1.d[1], $input_h1 @ AES block 4k+5 - mov high
fmov $ctr_t2d, $input_l2 @ AES block 4k+6 - mov low
cmp $input_ptr, $main_end_input_ptr @ LOOP CONTROL
fmov $ctr_t2.d[1], $input_h2 @ AES block 4k+6 - mov high
pmull $acc_h.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
eor $res0b, $ctr_t0b, $ctr0b @ AES block 4k+4 - result
fmov $ctr0d, $ctr96_b64x @ CTR block 4k+8
fmov $ctr0.d[1], $ctr32x @ CTR block 4k+8
rev $ctr32w, $rctr32w @ CTR block 4k+9
add $rctr32w, $rctr32w, #1 @ CTR block 4k+9
eor $res1b, $ctr_t1b, $ctr1b @ AES block 4k+5 - result
fmov $ctr1d, $ctr96_b64x @ CTR block 4k+9
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+9
aese $ctr3b, $rk12 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 12
fmov $ctr1.d[1], $ctr32x @ CTR block 4k+9
aese $ctr2b, $rk13 @ AES block 4k+6 - round 13
rev $ctr32w, $rctr32w @ CTR block 4k+10
st1 { $res0b}, [$output_ptr], #16 @ AES block 4k+4 - store result
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+10
eor $acc_lb, $acc_lb, $acc_hb @ MODULO - fold into low
fmov $ctr_t3.d[1], $input_h3 @ AES block 4k+7 - mov high
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
st1 { $res1b}, [$output_ptr], #16 @ AES block 4k+5 - store result
add $rctr32w, $rctr32w, #1 @ CTR block 4k+10
aese $ctr3b, $rk13 @ AES block 4k+7 - round 13
eor $res2b, $ctr_t2b, $ctr2b @ AES block 4k+6 - result
fmov $ctr2d, $ctr96_b64x @ CTR block 4k+10
st1 { $res2b}, [$output_ptr], #16 @ AES block 4k+6 - store result
fmov $ctr2.d[1], $ctr32x @ CTR block 4k+10
rev $ctr32w, $rctr32w @ CTR block 4k+11
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+11
eor $res3b, $ctr_t3b, $ctr3b @ AES block 4k+7 - result
st1 { $res3b}, [$output_ptr], #16 @ AES block 4k+7 - store result
b.lt L256_enc_main_loop
.L256_enc_prepretail: @ PREPRETAIL
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
rev64 $res2b, $res2b @ GHASH block 4k+2 (t0, t1, and t2 free)
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
fmov $ctr3d, $ctr96_b64x @ CTR block 4k+3
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
rev64 $res0b, $res0b @ GHASH block 4k (only t0 is free)
fmov $ctr3.d[1], $ctr32x @ CTR block 4k+3
ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
eor $res0b, $res0b, $acc_lb @ PRE 1
rev64 $res1b, $res1b @ GHASH block 4k+1 (t0 and t1 free)
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
mov $t0d, $res0.d[1] @ GHASH block 4k - mid
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
rev64 $res3b, $res3b @ GHASH block 4k+3 (t0, t1, t2 and t3 free)
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
add $rctr32w, $rctr32w, #1 @ CTR block 4k+3
pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
movi $mod_constant.8b, #0xc2
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
eor $acc_mb, $acc_mb, $acc_hb @ karatsuba tidy up
pmull $t1.1q, $acc_h.1d, $mod_constant.1d
ext $acc_hb, $acc_hb, $acc_hb, #8
aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
eor $acc_mb, $acc_mb, $acc_lb
aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
aese $ctr1b, $rk11 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 11
eor $acc_mb, $acc_mb, $t1.16b
aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
aese $ctr1b, $rk12 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 12
aese $ctr0b, $rk11 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 11
eor $acc_mb, $acc_mb, $acc_hb
aese $ctr3b, $rk11 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 11
aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
aese $ctr0b, $rk12 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 12
pmull $t1.1q, $acc_m.1d, $mod_constant.1d
aese $ctr2b, $rk11 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 11
ext $acc_mb, $acc_mb, $acc_mb, #8
aese $ctr3b, $rk12 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 12
aese $ctr1b, $rk13 @ AES block 4k+5 - round 13
eor $acc_lb, $acc_lb, $t1.16b
aese $ctr2b, $rk12 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 12
aese $ctr3b, $rk13 @ AES block 4k+7 - round 13
aese $ctr0b, $rk13 @ AES block 4k+4 - round 13
aese $ctr2b, $rk13 @ AES block 4k+6 - round 13
eor $acc_lb, $acc_lb, $acc_mb
.L256_enc_tail: @ TAIL
ext $t0.16b, $acc_lb, $acc_lb, #8 @ prepare final partial tag
sub $main_end_input_ptr, $end_input_ptr, $input_ptr @ main_end_input_ptr is number of bytes left to process
ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES block 4k+4 - load plaintext
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
eor $input_l0, $input_l0, $rk14_l @ AES block 4k+4 - round 14 low
eor $input_h0, $input_h0, $rk14_h @ AES block 4k+4 - round 14 high
cmp $main_end_input_ptr, #48
fmov $ctr_t0d, $input_l0 @ AES block 4k+4 - mov low
fmov $ctr_t0.d[1], $input_h0 @ AES block 4k+4 - mov high
eor $res1b, $ctr_t0b, $ctr0b @ AES block 4k+4 - result
b.gt .L256_enc_blocks_more_than_3
cmp $main_end_input_ptr, #32
mov $ctr3b, $ctr2b
movi $acc_l.8b, #0
movi $acc_h.8b, #0
sub $rctr32w, $rctr32w, #1
mov $ctr2b, $ctr1b
movi $acc_m.8b, #0
b.gt .L256_enc_blocks_more_than_2
mov $ctr3b, $ctr1b
sub $rctr32w, $rctr32w, #1
cmp $main_end_input_ptr, #16
b.gt .L256_enc_blocks_more_than_1
sub $rctr32w, $rctr32w, #1
b .L256_enc_blocks_less_than_1
.L256_enc_blocks_more_than_3: @ blocks left > 3
st1 { $res1b}, [$output_ptr], #16 @ AES final-3 block - store result
ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final-2 block - load input low & high
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
rev64 $res0b, $res1b @ GHASH final-3 block
eor $input_l0, $input_l0, $rk14_l @ AES final-2 block - round 14 low
eor $res0b, $res0b, $t0.16b @ feed in partial tag
eor $input_h0, $input_h0, $rk14_h @ AES final-2 block - round 14 high
mov $rk4d, $res0.d[1] @ GHASH final-3 block - mid
fmov $res1d, $input_l0 @ AES final-2 block - mov low
fmov $res1.d[1], $input_h0 @ AES final-2 block - mov high
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-3 block - mid
movi $t0.8b, #0 @ suppress further partial tag feed in
mov $acc_md, $h34k.d[1] @ GHASH final-3 block - mid
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH final-3 block - low
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH final-3 block - high
pmull $acc_m.1q, $rk4v.1d, $acc_m.1d @ GHASH final-3 block - mid
eor $res1b, $res1b, $ctr1b @ AES final-2 block - result
.L256_enc_blocks_more_than_2: @ blocks left > 2
st1 { $res1b}, [$output_ptr], #16 @ AES final-2 block - store result
ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final-1 block - load input low & high
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
rev64 $res0b, $res1b @ GHASH final-2 block
eor $input_l0, $input_l0, $rk14_l @ AES final-1 block - round 14 low
eor $res0b, $res0b, $t0.16b @ feed in partial tag
fmov $res1d, $input_l0 @ AES final-1 block - mov low
eor $input_h0, $input_h0, $rk14_h @ AES final-1 block - round 14 high
fmov $res1.d[1], $input_h0 @ AES final-1 block - mov high
movi $t0.8b, #0 @ suppress further partial tag feed in
pmull2 $rk2q1, $res0.2d, $h3.2d @ GHASH final-2 block - high
mov $rk4d, $res0.d[1] @ GHASH final-2 block - mid
pmull $rk3q1, $res0.1d, $h3.1d @ GHASH final-2 block - low
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-2 block - mid
eor $res1b, $res1b, $ctr2b @ AES final-1 block - result
eor $acc_hb, $acc_hb, $rk2 @ GHASH final-2 block - high
pmull $rk4v.1q, $rk4v.1d, $h34k.1d @ GHASH final-2 block - mid
eor $acc_lb, $acc_lb, $rk3 @ GHASH final-2 block - low
eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-2 block - mid
.L256_enc_blocks_more_than_1: @ blocks left > 1
st1 { $res1b}, [$output_ptr], #16 @ AES final-1 block - store result
rev64 $res0b, $res1b @ GHASH final-1 block
ldp $input_l0, $input_h0, [$input_ptr], #16 @ AES final block - load input low & high
-
+#ifdef __AARCH64EB__
+ rev $input_l0, $input_l0
+ rev $input_h0, $input_h0
+#endif
eor $res0b, $res0b, $t0.16b @ feed in partial tag
movi $t0.8b, #0 @ suppress further partial tag feed in
eor $input_l0, $input_l0, $rk14_l @ AES final block - round 14 low
mov $rk4d, $res0.d[1] @ GHASH final-1 block - mid
pmull2 $rk2q1, $res0.2d, $h2.2d @ GHASH final-1 block - high
eor $input_h0, $input_h0, $rk14_h @ AES final block - round 14 high
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-1 block - mid
eor $acc_hb, $acc_hb, $rk2 @ GHASH final-1 block - high
ins $rk4v.d[1], $rk4v.d[0] @ GHASH final-1 block - mid
fmov $res1d, $input_l0 @ AES final block - mov low
fmov $res1.d[1], $input_h0 @ AES final block - mov high
pmull2 $rk4v.1q, $rk4v.2d, $h12k.2d @ GHASH final-1 block - mid
pmull $rk3q1, $res0.1d, $h2.1d @ GHASH final-1 block - low
eor $res1b, $res1b, $ctr3b @ AES final block - result
eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-1 block - mid
eor $acc_lb, $acc_lb, $rk3 @ GHASH final-1 block - low
.L256_enc_blocks_less_than_1: @ blocks left <= 1
and $bit_length, $bit_length, #127 @ bit_length %= 128
mvn $rk14_l, xzr @ rk14_l = 0xffffffffffffffff
sub $bit_length, $bit_length, #128 @ bit_length -= 128
neg $bit_length, $bit_length @ bit_length = 128 - #bits in input (in range [1,128])
ld1 { $rk0}, [$output_ptr] @ load existing bytes where the possibly partial last block is to be stored
mvn $rk14_h, xzr @ rk14_h = 0xffffffffffffffff
and $bit_length, $bit_length, #127 @ bit_length %= 128
lsr $rk14_h, $rk14_h, $bit_length @ rk14_h is mask for top 64b of last block
cmp $bit_length, #64
csel $input_l0, $rk14_l, $rk14_h, lt
csel $input_h0, $rk14_h, xzr, lt
fmov $ctr0d, $input_l0 @ ctr0b is mask for last block
fmov $ctr0.d[1], $input_h0
and $res1b, $res1b, $ctr0b @ possibly partial last block has zeroes in highest bits
rev64 $res0b, $res1b @ GHASH final block
eor $res0b, $res0b, $t0.16b @ feed in partial tag
bif $res1b, $rk0, $ctr0b @ insert existing bytes in top end of result before storing
pmull2 $rk2q1, $res0.2d, $h1.2d @ GHASH final block - high
mov $t0d, $res0.d[1] @ GHASH final block - mid
+#ifndef __AARCH64EB__
rev $ctr32w, $rctr32w
+#else
+ mov $ctr32w, $rctr32w
+#endif
pmull $rk3q1, $res0.1d, $h1.1d @ GHASH final block - low
eor $acc_hb, $acc_hb, $rk2 @ GHASH final block - high
eor $t0.8b, $t0.8b, $res0.8b @ GHASH final block - mid
pmull $t0.1q, $t0.1d, $h12k.1d @ GHASH final block - mid
eor $acc_lb, $acc_lb, $rk3 @ GHASH final block - low
eor $acc_mb, $acc_mb, $t0.16b @ GHASH final block - mid
movi $mod_constant.8b, #0xc2
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
pmull $acc_h.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
str $ctr32w, [$counter, #12] @ store the updated counter
st1 { $res1b}, [$output_ptr] @ store all 16B
eor $acc_lb, $acc_lb, $acc_hb @ MODULO - fold into low
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
ext $acc_lb, $acc_lb, $acc_lb, #8
rev64 $acc_lb, $acc_lb
mov x0, $len
st1 { $acc_l.16b }, [$current_tag]
ldp x21, x22, [sp, #16]
ldp x23, x24, [sp, #32]
ldp d8, d9, [sp, #48]
ldp d10, d11, [sp, #64]
ldp d12, d13, [sp, #80]
ldp d14, d15, [sp, #96]
ldp x19, x20, [sp], #112
ret
.L256_enc_ret:
mov w0, #0x0
ret
.size aes_gcm_enc_256_kernel,.-aes_gcm_enc_256_kernel
___
{
my $t8="v4";
my $t8d="d4";
my $t9="v6";
my $t9d="d6";
#########################################################################################
# size_t aes_gcm_dec_256_kernel(const unsigned char *in,
# size_t len,
# unsigned char *out,
# const void *key,
# unsigned char ivec[16],
# u64 *Xi);
#
$code.=<<___;
.global aes_gcm_dec_256_kernel
.type aes_gcm_dec_256_kernel,%function
.align 4
aes_gcm_dec_256_kernel:
cbz x1, .L256_dec_ret
stp x19, x20, [sp, #-112]!
mov x16, x4
mov x8, x5
stp x21, x22, [sp, #16]
stp x23, x24, [sp, #32]
stp d8, d9, [sp, #48]
stp d10, d11, [sp, #64]
stp d12, d13, [sp, #80]
stp d14, d15, [sp, #96]
lsr $main_end_input_ptr, $bit_length, #3 @ byte_len
mov $len, $main_end_input_ptr
ldp $ctr96_b64x, $ctr96_t32x, [$counter] @ ctr96_b64, ctr96_t32
-
- ldr $rk8q, [$cc, #128] @ load rk8
+#ifdef __AARCH64EB__
+ rev $ctr96_b64x, $ctr96_b64x
+ rev $ctr96_t32x, $ctr96_t32x
+#endif
+ ldp $rk14_l, $rk14_h, [$cc, #224] @ load rk14
+#ifdef __AARCH64EB__
+ ror $rk14_h, $rk14_h, #32
+ ror $rk14_l, $rk14_l, #32
+#endif
+ ld1 {$rk0s}, [$cc], #16 @ load rk0
sub $main_end_input_ptr, $main_end_input_ptr, #1 @ byte_len - 1
- ldr $rk7q, [$cc, #112] @ load rk7
+ ld1 {$rk1s}, [$cc], #16 @ load rk1
and $main_end_input_ptr, $main_end_input_ptr, #0xffffffffffffffc0 @ number of bytes to be processed in main loop (at least 1 byte must be handled by tail)
add $end_input_ptr, $input_ptr, $bit_length, lsr #3 @ end_input_ptr
- ldr $rk6q, [$cc, #96] @ load rk6
+ ld1 {$rk2s}, [$cc], #16 @ load rk2
lsr $rctr32x, $ctr96_t32x, #32
- ldr $rk5q, [$cc, #80] @ load rk5
+ ld1 {$rk3s}, [$cc], #16 @ load rk3
orr $ctr96_t32w, $ctr96_t32w, $ctr96_t32w
- ldr $rk3q, [$cc, #48] @ load rk3
+ ld1 {$rk4s}, [$cc], #16 @ load rk4
add $main_end_input_ptr, $main_end_input_ptr, $input_ptr
rev $rctr32w, $rctr32w @ rev_ctr32
add $rctr32w, $rctr32w, #1 @ increment rev_ctr32
fmov $ctr3d, $ctr96_b64x @ CTR block 3
rev $ctr32w, $rctr32w @ CTR block 1
add $rctr32w, $rctr32w, #1 @ CTR block 1
fmov $ctr1d, $ctr96_b64x @ CTR block 1
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 1
ld1 { $ctr0b}, [$counter] @ special case vector load initial counter so we can start first AES block as quickly as possible
fmov $ctr1.d[1], $ctr32x @ CTR block 1
rev $ctr32w, $rctr32w @ CTR block 2
add $rctr32w, $rctr32w, #1 @ CTR block 2
fmov $ctr2d, $ctr96_b64x @ CTR block 2
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 2
fmov $ctr2.d[1], $ctr32x @ CTR block 2
rev $ctr32w, $rctr32w @ CTR block 3
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 3
- ldr $rk0q, [$cc, #0] @ load rk0
+ ld1 {$rk5s}, [$cc], #16 @ load rk5
fmov $ctr3.d[1], $ctr32x @ CTR block 3
add $rctr32w, $rctr32w, #1 @ CTR block 3
- ldr $rk4q, [$cc, #64] @ load rk4
+ ld1 {$rk6s}, [$cc], #16 @ load rk6
- ldr $rk13q, [$cc, #208] @ load rk13
+ ld1 {$rk7s}, [$cc], #16 @ load rk7
- ldr $rk1q, [$cc, #16] @ load rk1
+ ld1 {$rk8s}, [$cc], #16 @ load rk8
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 0
ldr $h3q, [$current_tag, #80] @ load h3l | h3h
+#ifndef __AARCH64EB__
ext $h3b, $h3b, $h3b, #8
+#endif
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 0
ldr $h4q, [$current_tag, #112] @ load h4l | h4h
+#ifndef __AARCH64EB__
ext $h4b, $h4b, $h4b, #8
+#endif
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 0
ldr $h2q, [$current_tag, #64] @ load h2l | h2h
+#ifndef __AARCH64EB__
ext $h2b, $h2b, $h2b, #8
+#endif
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 0
- ldr $rk2q, [$cc, #32] @ load rk2
+ ld1 {$rk9s}, [$cc], #16 @ load rk9
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 1
- ldp $rk14_l, $rk14_h, [$cc, #224] @ load rk14
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 1
ld1 { $acc_lb}, [$current_tag]
ext $acc_lb, $acc_lb, $acc_lb, #8
rev64 $acc_lb, $acc_lb
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 1
- ldr $rk9q, [$cc, #144] @ load rk9
+ ld1 {$rk10s}, [$cc], #16 @ load rk10
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 1
- ldr $rk12q, [$cc, #192] @ load rk12
+ ld1 {$rk11s}, [$cc], #16 @ load rk11
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 2
ldr $h1q, [$current_tag, #32] @ load h1l | h1h
+#ifndef __AARCH64EB__
ext $h1b, $h1b, $h1b, #8
-
+#endif
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 2
- ldr $rk10q, [$cc, #160] @ load rk10
+ ld1 {$rk12s}, [$cc], #16 @ load rk12
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 2
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 3
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 2
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 3
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 4
cmp $input_ptr, $main_end_input_ptr @ check if we have <= 4 blocks
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 3
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 3
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 4
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 4
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 4
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 5
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 5
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 5
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 5
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 6
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 6
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 6
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 6
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 7
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 7
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 7
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 8
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 7
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 8
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 8
aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 9
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 8
- ldr $rk11q, [$cc, #176] @ load rk11
+ ld1 {$rk13s}, [$cc], #16 @ load rk13
aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 9
aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 10
aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 9
aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 10
aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 9
aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 10
aese $ctr0b, $rk11 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 11
aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 10
aese $ctr3b, $rk11 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 11
aese $ctr1b, $rk11 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 11
aese $ctr2b, $rk11 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 11
trn1 $acc_h.2d, $h3.2d, $h4.2d @ h4h | h3h
trn2 $h34k.2d, $h3.2d, $h4.2d @ h4l | h3l
trn1 $t0.2d, $h1.2d, $h2.2d @ h2h | h1h
trn2 $h12k.2d, $h1.2d, $h2.2d @ h2l | h1l
aese $ctr1b, $rk12 \n aesmc $ctr1b, $ctr1b @ AES block 1 - round 12
aese $ctr0b, $rk12 \n aesmc $ctr0b, $ctr0b @ AES block 0 - round 12
aese $ctr2b, $rk12 \n aesmc $ctr2b, $ctr2b @ AES block 2 - round 12
aese $ctr3b, $rk12 \n aesmc $ctr3b, $ctr3b @ AES block 3 - round 12
eor $h34k.16b, $h34k.16b, $acc_h.16b @ h4k | h3k
aese $ctr1b, $rk13 @ AES block 1 - round 13
aese $ctr2b, $rk13 @ AES block 2 - round 13
eor $h12k.16b, $h12k.16b, $t0.16b @ h2k | h1k
aese $ctr3b, $rk13 @ AES block 3 - round 13
aese $ctr0b, $rk13 @ AES block 0 - round 13
b.ge .L256_dec_tail @ handle tail
- ldr $res0q, [$input_ptr, #0] @ AES block 0 - load ciphertext
-
- ldr $res1q, [$input_ptr, #16] @ AES block 1 - load ciphertext
+ ld1 {$res0b, $res1b}, [$input_ptr], #32 @ AES block 0,1 - load ciphertext
rev $ctr32w, $rctr32w @ CTR block 4
eor $ctr0b, $res0b, $ctr0b @ AES block 0 - result
eor $ctr1b, $res1b, $ctr1b @ AES block 1 - result
rev64 $res1b, $res1b @ GHASH block 1
- ldr $res3q, [$input_ptr, #48] @ AES block 3 - load ciphertext
+ ld1 {$res2b}, [$input_ptr], #16 @ AES block 2 - load ciphertext
mov $output_h0, $ctr0.d[1] @ AES block 0 - mov high
mov $output_l0, $ctr0.d[0] @ AES block 0 - mov low
rev64 $res0b, $res0b @ GHASH block 0
add $rctr32w, $rctr32w, #1 @ CTR block 4
fmov $ctr0d, $ctr96_b64x @ CTR block 4
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4
fmov $ctr0.d[1], $ctr32x @ CTR block 4
rev $ctr32w, $rctr32w @ CTR block 5
add $rctr32w, $rctr32w, #1 @ CTR block 5
mov $output_l1, $ctr1.d[0] @ AES block 1 - mov low
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 5
mov $output_h1, $ctr1.d[1] @ AES block 1 - mov high
eor $output_h0, $output_h0, $rk14_h @ AES block 0 - round 14 high
-
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
eor $output_l0, $output_l0, $rk14_l @ AES block 0 - round 14 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES block 0 - store result
fmov $ctr1d, $ctr96_b64x @ CTR block 5
- ldr $res2q, [$input_ptr, #32] @ AES block 2 - load ciphertext
- add $input_ptr, $input_ptr, #64 @ AES input_ptr update
+ ld1 {$res3b}, [$input_ptr], #16 @ AES block 3 - load ciphertext
fmov $ctr1.d[1], $ctr32x @ CTR block 5
rev $ctr32w, $rctr32w @ CTR block 6
add $rctr32w, $rctr32w, #1 @ CTR block 6
eor $output_l1, $output_l1, $rk14_l @ AES block 1 - round 14 low
+#ifdef __AARCH64EB__
+ rev $output_l1, $output_l1
+#endif
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 6
eor $output_h1, $output_h1, $rk14_h @ AES block 1 - round 14 high
+#ifdef __AARCH64EB__
+ rev $output_h1, $output_h1
+#endif
stp $output_l1, $output_h1, [$output_ptr], #16 @ AES block 1 - store result
eor $ctr2b, $res2b, $ctr2b @ AES block 2 - result
cmp $input_ptr, $main_end_input_ptr @ check if we have <= 8 blocks
b.ge .L256_dec_prepretail @ do prepretail
.L256_dec_main_loop: @ main loop start
mov $output_l2, $ctr2.d[0] @ AES block 4k+2 - mov low
ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
eor $ctr3b, $res3b, $ctr3b @ AES block 4k+3 - result
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
mov $output_h2, $ctr2.d[1] @ AES block 4k+2 - mov high
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
fmov $ctr2d, $ctr96_b64x @ CTR block 4k+6
fmov $ctr2.d[1], $ctr32x @ CTR block 4k+6
eor $res0b, $res0b, $acc_lb @ PRE 1
rev $ctr32w, $rctr32w @ CTR block 4k+7
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
mov $output_h3, $ctr3.d[1] @ AES block 4k+3 - mov high
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
mov $output_l3, $ctr3.d[0] @ AES block 4k+3 - mov low
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
mov $t0d, $res0.d[1] @ GHASH block 4k - mid
fmov $ctr3d, $ctr96_b64x @ CTR block 4k+7
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+7
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
fmov $ctr3.d[1], $ctr32x @ CTR block 4k+7
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
eor $output_h2, $output_h2, $rk14_h @ AES block 4k+2 - round 14 high
-
+#ifdef __AARCH64EB__
+ rev $output_h2, $output_h2
+#endif
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
rev64 $res2b, $res2b @ GHASH block 4k+2
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
eor $output_l2, $output_l2, $rk14_l @ AES block 4k+2 - round 14 low
-
+#ifdef __AARCH64EB__
+ rev $output_l2, $output_l2
+#endif
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
stp $output_l2, $output_h2, [$output_ptr], #16 @ AES block 4k+2 - store result
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
rev64 $res3b, $res3b @ GHASH block 4k+3
pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
eor $output_l3, $output_l3, $rk14_l @ AES block 4k+3 - round 14 low
-
+#ifdef __AARCH64EB__
+ rev $output_l3, $output_l3
+#endif
pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
eor $output_h3, $output_h3, $rk14_h @ AES block 4k+3 - round 14 high
+#ifdef __AARCH64EB__
+ rev $output_h3, $output_h3
+#endif
eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
add $rctr32w, $rctr32w, #1 @ CTR block 4k+7
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
rev $ctr32w, $rctr32w @ CTR block 4k+8
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
add $rctr32w, $rctr32w, #1 @ CTR block 4k+8
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+8
eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
movi $mod_constant.8b, #0xc2
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
aese $ctr0b, $rk11 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 11
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
aese $ctr0b, $rk12 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 12
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
- ldr $res0q, [$input_ptr, #0] @ AES block 4k+4 - load ciphertext
+ ld1 {$res0b}, [$input_ptr], #16 @ AES block 4k+4 - load ciphertext
aese $ctr0b, $rk13 @ AES block 4k+4 - round 13
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
- ldr $res1q, [$input_ptr, #16] @ AES block 4k+5 - load ciphertext
+ ld1 {$res1b}, [$input_ptr], #16 @ AES block 4k+5 - load ciphertext
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
eor $ctr0b, $res0b, $ctr0b @ AES block 4k+4 - result
aese $ctr1b, $rk11 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 11
stp $output_l3, $output_h3, [$output_ptr], #16 @ AES block 4k+3 - store result
aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
- ldr $res3q, [$input_ptr, #48] @ AES block 4k+7 - load ciphertext
+ ld1 {$res2b}, [$input_ptr], #16 @ AES block 4k+6 - load ciphertext
aese $ctr1b, $rk12 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 12
- ldr $res2q, [$input_ptr, #32] @ AES block 4k+6 - load ciphertext
+ ld1 {$res3b}, [$input_ptr], #16 @ AES block 4k+7 - load ciphertext
aese $ctr2b, $rk11 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 11
mov $output_h0, $ctr0.d[1] @ AES block 4k+4 - mov high
aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
aese $ctr1b, $rk13 @ AES block 4k+5 - round 13
- add $input_ptr, $input_ptr, #64 @ AES input_ptr update
mov $output_l0, $ctr0.d[0] @ AES block 4k+4 - mov low
aese $ctr2b, $rk12 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 12
fmov $ctr0d, $ctr96_b64x @ CTR block 4k+8
aese $ctr3b, $rk11 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 11
fmov $ctr0.d[1], $ctr32x @ CTR block 4k+8
pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
eor $ctr1b, $res1b, $ctr1b @ AES block 4k+5 - result
rev $ctr32w, $rctr32w @ CTR block 4k+9
aese $ctr2b, $rk13 @ AES block 4k+6 - round 13
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+9
cmp $input_ptr, $main_end_input_ptr @ LOOP CONTROL
add $rctr32w, $rctr32w, #1 @ CTR block 4k+9
eor $output_l0, $output_l0, $rk14_l @ AES block 4k+4 - round 14 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
eor $output_h0, $output_h0, $rk14_h @ AES block 4k+4 - round 14 high
-
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
mov $output_h1, $ctr1.d[1] @ AES block 4k+5 - mov high
eor $ctr2b, $res2b, $ctr2b @ AES block 4k+6 - result
eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
aese $ctr3b, $rk12 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 12
mov $output_l1, $ctr1.d[0] @ AES block 4k+5 - mov low
fmov $ctr1d, $ctr96_b64x @ CTR block 4k+9
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
fmov $ctr1.d[1], $ctr32x @ CTR block 4k+9
rev $ctr32w, $rctr32w @ CTR block 4k+10
add $rctr32w, $rctr32w, #1 @ CTR block 4k+10
aese $ctr3b, $rk13 @ AES block 4k+7 - round 13
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+10
rev64 $res1b, $res1b @ GHASH block 4k+5
eor $output_h1, $output_h1, $rk14_h @ AES block 4k+5 - round 14 high
+#ifdef __AARCH64EB__
+ rev $output_h1, $output_h1
+#endif
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES block 4k+4 - store result
eor $output_l1, $output_l1, $rk14_l @ AES block 4k+5 - round 14 low
+#ifdef __AARCH64EB__
+ rev $output_l1, $output_l1
+#endif
stp $output_l1, $output_h1, [$output_ptr], #16 @ AES block 4k+5 - store result
rev64 $res0b, $res0b @ GHASH block 4k+4
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
b.lt .L256_dec_main_loop
.L256_dec_prepretail: @ PREPRETAIL
ext $acc_lb, $acc_lb, $acc_lb, #8 @ PRE 0
mov $output_l2, $ctr2.d[0] @ AES block 4k+2 - mov low
eor $ctr3b, $res3b, $ctr3b @ AES block 4k+3 - result
aese $ctr0b, $rk0 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 0
mov $output_h2, $ctr2.d[1] @ AES block 4k+2 - mov high
aese $ctr1b, $rk0 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 0
fmov $ctr2d, $ctr96_b64x @ CTR block 4k+6
fmov $ctr2.d[1], $ctr32x @ CTR block 4k+6
rev $ctr32w, $rctr32w @ CTR block 4k+7
eor $res0b, $res0b, $acc_lb @ PRE 1
rev64 $res2b, $res2b @ GHASH block 4k+2
orr $ctr32x, $ctr96_t32x, $ctr32x, lsl #32 @ CTR block 4k+7
mov $output_l3, $ctr3.d[0] @ AES block 4k+3 - mov low
aese $ctr1b, $rk1 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 1
mov $output_h3, $ctr3.d[1] @ AES block 4k+3 - mov high
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH block 4k - low
mov $t0d, $res0.d[1] @ GHASH block 4k - mid
fmov $ctr3d, $ctr96_b64x @ CTR block 4k+7
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH block 4k - high
fmov $ctr3.d[1], $ctr32x @ CTR block 4k+7
aese $ctr2b, $rk0 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 0
mov $acc_md, $h34k.d[1] @ GHASH block 4k - mid
aese $ctr0b, $rk1 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 1
eor $t0.8b, $t0.8b, $res0.8b @ GHASH block 4k - mid
pmull2 $t1.1q, $res1.2d, $h3.2d @ GHASH block 4k+1 - high
aese $ctr2b, $rk1 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 1
rev64 $res3b, $res3b @ GHASH block 4k+3
aese $ctr3b, $rk0 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 0
pmull $acc_m.1q, $t0.1d, $acc_m.1d @ GHASH block 4k - mid
eor $acc_hb, $acc_hb, $t1.16b @ GHASH block 4k+1 - high
pmull $t2.1q, $res1.1d, $h3.1d @ GHASH block 4k+1 - low
aese $ctr3b, $rk1 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 1
mov $t3d, $res1.d[1] @ GHASH block 4k+1 - mid
aese $ctr0b, $rk2 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 2
aese $ctr1b, $rk2 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 2
eor $acc_lb, $acc_lb, $t2.16b @ GHASH block 4k+1 - low
aese $ctr2b, $rk2 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 2
aese $ctr0b, $rk3 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 3
mov $t6d, $res2.d[1] @ GHASH block 4k+2 - mid
aese $ctr3b, $rk2 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 2
eor $t3.8b, $t3.8b, $res1.8b @ GHASH block 4k+1 - mid
pmull $t5.1q, $res2.1d, $h2.1d @ GHASH block 4k+2 - low
aese $ctr0b, $rk4 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 4
aese $ctr3b, $rk3 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 3
eor $t6.8b, $t6.8b, $res2.8b @ GHASH block 4k+2 - mid
pmull $t3.1q, $t3.1d, $h34k.1d @ GHASH block 4k+1 - mid
aese $ctr0b, $rk5 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 5
eor $acc_lb, $acc_lb, $t5.16b @ GHASH block 4k+2 - low
aese $ctr3b, $rk4 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 4
pmull2 $t7.1q, $res3.2d, $h1.2d @ GHASH block 4k+3 - high
eor $acc_mb, $acc_mb, $t3.16b @ GHASH block 4k+1 - mid
pmull2 $t4.1q, $res2.2d, $h2.2d @ GHASH block 4k+2 - high
aese $ctr3b, $rk5 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 5
ins $t6.d[1], $t6.d[0] @ GHASH block 4k+2 - mid
aese $ctr2b, $rk3 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 3
aese $ctr1b, $rk3 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 3
eor $acc_hb, $acc_hb, $t4.16b @ GHASH block 4k+2 - high
pmull $t8.1q, $res3.1d, $h1.1d @ GHASH block 4k+3 - low
aese $ctr2b, $rk4 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 4
mov $t9d, $res3.d[1] @ GHASH block 4k+3 - mid
aese $ctr1b, $rk4 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 4
pmull2 $t6.1q, $t6.2d, $h12k.2d @ GHASH block 4k+2 - mid
aese $ctr2b, $rk5 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 5
eor $t9.8b, $t9.8b, $res3.8b @ GHASH block 4k+3 - mid
aese $ctr1b, $rk5 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 5
aese $ctr3b, $rk6 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 6
eor $acc_mb, $acc_mb, $t6.16b @ GHASH block 4k+2 - mid
aese $ctr2b, $rk6 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 6
aese $ctr0b, $rk6 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 6
movi $mod_constant.8b, #0xc2
aese $ctr1b, $rk6 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 6
eor $acc_lb, $acc_lb, $t8.16b @ GHASH block 4k+3 - low
pmull $t9.1q, $t9.1d, $h12k.1d @ GHASH block 4k+3 - mid
aese $ctr3b, $rk7 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 7
eor $acc_hb, $acc_hb, $t7.16b @ GHASH block 4k+3 - high
aese $ctr1b, $rk7 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 7
aese $ctr0b, $rk7 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 7
eor $acc_mb, $acc_mb, $t9.16b @ GHASH block 4k+3 - mid
aese $ctr3b, $rk8 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 8
aese $ctr2b, $rk7 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 7
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
aese $ctr1b, $rk8 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 8
aese $ctr0b, $rk8 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 8
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
aese $ctr2b, $rk8 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 8
aese $ctr1b, $rk9 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 9
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
aese $ctr2b, $rk9 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 9
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
aese $ctr3b, $rk9 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 9
aese $ctr0b, $rk9 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 9
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
aese $ctr2b, $rk10 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 10
aese $ctr3b, $rk10 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 10
aese $ctr0b, $rk10 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 10
eor $output_h2, $output_h2, $rk14_h @ AES block 4k+2 - round 14 high
-
+#ifdef __AARCH64EB__
+ rev $output_h2, $output_h2
+#endif
aese $ctr1b, $rk10 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 10
eor $output_l3, $output_l3, $rk14_l @ AES block 4k+3 - round 14 low
-
+#ifdef __AARCH64EB__
+ rev $output_l3, $output_l3
+#endif
aese $ctr2b, $rk11 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 11
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
aese $ctr0b, $rk11 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 11
add $rctr32w, $rctr32w, #1 @ CTR block 4k+7
aese $ctr1b, $rk11 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 11
eor $output_l2, $output_l2, $rk14_l @ AES block 4k+2 - round 14 low
+#ifdef __AARCH64EB__
+ rev $output_l2, $output_l2
+#endif
aese $ctr2b, $rk12 \n aesmc $ctr2b, $ctr2b @ AES block 4k+6 - round 12
pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
eor $output_h3, $output_h3, $rk14_h @ AES block 4k+3 - round 14 high
+#ifdef __AARCH64EB__
+ rev $output_h3, $output_h3
+#endif
aese $ctr3b, $rk11 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 11
stp $output_l2, $output_h2, [$output_ptr], #16 @ AES block 4k+2 - store result
aese $ctr1b, $rk12 \n aesmc $ctr1b, $ctr1b @ AES block 4k+5 - round 12
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
aese $ctr0b, $rk12 \n aesmc $ctr0b, $ctr0b @ AES block 4k+4 - round 12
stp $output_l3, $output_h3, [$output_ptr], #16 @ AES block 4k+3 - store result
aese $ctr3b, $rk12 \n aesmc $ctr3b, $ctr3b @ AES block 4k+7 - round 12
eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
aese $ctr1b, $rk13 @ AES block 4k+5 - round 13
aese $ctr0b, $rk13 @ AES block 4k+4 - round 13
aese $ctr3b, $rk13 @ AES block 4k+7 - round 13
aese $ctr2b, $rk13 @ AES block 4k+6 - round 13
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
.L256_dec_tail: @ TAIL
sub $main_end_input_ptr, $end_input_ptr, $input_ptr @ main_end_input_ptr is number of bytes left to process
ld1 { $res1b}, [$input_ptr], #16 @ AES block 4k+4 - load ciphertext
eor $ctr0b, $res1b, $ctr0b @ AES block 4k+4 - result
mov $output_l0, $ctr0.d[0] @ AES block 4k+4 - mov low
mov $output_h0, $ctr0.d[1] @ AES block 4k+4 - mov high
ext $t0.16b, $acc_lb, $acc_lb, #8 @ prepare final partial tag
cmp $main_end_input_ptr, #48
eor $output_l0, $output_l0, $rk14_l @ AES block 4k+4 - round 14 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
eor $output_h0, $output_h0, $rk14_h @ AES block 4k+4 - round 14 high
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
b.gt .L256_dec_blocks_more_than_3
sub $rctr32w, $rctr32w, #1
mov $ctr3b, $ctr2b
movi $acc_m.8b, #0
movi $acc_l.8b, #0
cmp $main_end_input_ptr, #32
movi $acc_h.8b, #0
mov $ctr2b, $ctr1b
b.gt .L256_dec_blocks_more_than_2
sub $rctr32w, $rctr32w, #1
mov $ctr3b, $ctr1b
cmp $main_end_input_ptr, #16
b.gt .L256_dec_blocks_more_than_1
sub $rctr32w, $rctr32w, #1
b .L256_dec_blocks_less_than_1
.L256_dec_blocks_more_than_3: @ blocks left > 3
rev64 $res0b, $res1b @ GHASH final-3 block
ld1 { $res1b}, [$input_ptr], #16 @ AES final-2 block - load ciphertext
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-3 block - store result
mov $acc_md, $h34k.d[1] @ GHASH final-3 block - mid
eor $res0b, $res0b, $t0.16b @ feed in partial tag
eor $ctr0b, $res1b, $ctr1b @ AES final-2 block - result
mov $rk4d, $res0.d[1] @ GHASH final-3 block - mid
mov $output_l0, $ctr0.d[0] @ AES final-2 block - mov low
mov $output_h0, $ctr0.d[1] @ AES final-2 block - mov high
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-3 block - mid
movi $t0.8b, #0 @ suppress further partial tag feed in
pmull2 $acc_h.1q, $res0.2d, $h4.2d @ GHASH final-3 block - high
pmull $acc_m.1q, $rk4v.1d, $acc_m.1d @ GHASH final-3 block - mid
eor $output_l0, $output_l0, $rk14_l @ AES final-2 block - round 14 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
pmull $acc_l.1q, $res0.1d, $h4.1d @ GHASH final-3 block - low
eor $output_h0, $output_h0, $rk14_h @ AES final-2 block - round 14 high
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
.L256_dec_blocks_more_than_2: @ blocks left > 2
rev64 $res0b, $res1b @ GHASH final-2 block
ld1 { $res1b}, [$input_ptr], #16 @ AES final-1 block - load ciphertext
eor $res0b, $res0b, $t0.16b @ feed in partial tag
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-2 block - store result
eor $ctr0b, $res1b, $ctr2b @ AES final-1 block - result
mov $rk4d, $res0.d[1] @ GHASH final-2 block - mid
pmull $rk3q1, $res0.1d, $h3.1d @ GHASH final-2 block - low
pmull2 $rk2q1, $res0.2d, $h3.2d @ GHASH final-2 block - high
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-2 block - mid
mov $output_l0, $ctr0.d[0] @ AES final-1 block - mov low
mov $output_h0, $ctr0.d[1] @ AES final-1 block - mov high
eor $acc_lb, $acc_lb, $rk3 @ GHASH final-2 block - low
movi $t0.8b, #0 @ suppress further partial tag feed in
pmull $rk4v.1q, $rk4v.1d, $h34k.1d @ GHASH final-2 block - mid
eor $acc_hb, $acc_hb, $rk2 @ GHASH final-2 block - high
eor $output_l0, $output_l0, $rk14_l @ AES final-1 block - round 14 low
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-2 block - mid
eor $output_h0, $output_h0, $rk14_h @ AES final-1 block - round 14 high
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
.L256_dec_blocks_more_than_1: @ blocks left > 1
stp $output_l0, $output_h0, [$output_ptr], #16 @ AES final-1 block - store result
rev64 $res0b, $res1b @ GHASH final-1 block
ld1 { $res1b}, [$input_ptr], #16 @ AES final block - load ciphertext
eor $res0b, $res0b, $t0.16b @ feed in partial tag
movi $t0.8b, #0 @ suppress further partial tag feed in
mov $rk4d, $res0.d[1] @ GHASH final-1 block - mid
eor $ctr0b, $res1b, $ctr3b @ AES final block - result
pmull2 $rk2q1, $res0.2d, $h2.2d @ GHASH final-1 block - high
eor $rk4v.8b, $rk4v.8b, $res0.8b @ GHASH final-1 block - mid
pmull $rk3q1, $res0.1d, $h2.1d @ GHASH final-1 block - low
mov $output_l0, $ctr0.d[0] @ AES final block - mov low
ins $rk4v.d[1], $rk4v.d[0] @ GHASH final-1 block - mid
mov $output_h0, $ctr0.d[1] @ AES final block - mov high
pmull2 $rk4v.1q, $rk4v.2d, $h12k.2d @ GHASH final-1 block - mid
eor $output_l0, $output_l0, $rk14_l @ AES final block - round 14 low
-
+#ifdef __AARCH64EB__
+ rev $output_l0, $output_l0
+#endif
eor $acc_lb, $acc_lb, $rk3 @ GHASH final-1 block - low
eor $acc_hb, $acc_hb, $rk2 @ GHASH final-1 block - high
eor $acc_mb, $acc_mb, $rk4v.16b @ GHASH final-1 block - mid
eor $output_h0, $output_h0, $rk14_h @ AES final block - round 14 high
+#ifdef __AARCH64EB__
+ rev $output_h0, $output_h0
+#endif
.L256_dec_blocks_less_than_1: @ blocks left <= 1
and $bit_length, $bit_length, #127 @ bit_length %= 128
mvn $rk14_h, xzr @ rk14_h = 0xffffffffffffffff
sub $bit_length, $bit_length, #128 @ bit_length -= 128
mvn $rk14_l, xzr @ rk14_l = 0xffffffffffffffff
ldp $end_input_ptr, $main_end_input_ptr, [$output_ptr] @ load existing bytes we need to not overwrite
neg $bit_length, $bit_length @ bit_length = 128 - #bits in input (in range [1,128])
and $bit_length, $bit_length, #127 @ bit_length %= 128
lsr $rk14_h, $rk14_h, $bit_length @ rk14_h is mask for top 64b of last block
cmp $bit_length, #64
csel $ctr32x, $rk14_l, $rk14_h, lt
csel $ctr96_b64x, $rk14_h, xzr, lt
fmov $ctr0d, $ctr32x @ ctr0b is mask for last block
and $output_l0, $output_l0, $ctr32x
mov $ctr0.d[1], $ctr96_b64x
bic $end_input_ptr, $end_input_ptr, $ctr32x @ mask out low existing bytes
+#ifndef __AARCH64EB__
rev $ctr32w, $rctr32w
+#else
+ mov $ctr32w, $rctr32w
+#endif
bic $main_end_input_ptr, $main_end_input_ptr, $ctr96_b64x @ mask out high existing bytes
orr $output_l0, $output_l0, $end_input_ptr
and $output_h0, $output_h0, $ctr96_b64x
orr $output_h0, $output_h0, $main_end_input_ptr
and $res1b, $res1b, $ctr0b @ possibly partial last block has zeroes in highest bits
rev64 $res0b, $res1b @ GHASH final block
eor $res0b, $res0b, $t0.16b @ feed in partial tag
pmull $rk3q1, $res0.1d, $h1.1d @ GHASH final block - low
mov $t0d, $res0.d[1] @ GHASH final block - mid
eor $t0.8b, $t0.8b, $res0.8b @ GHASH final block - mid
pmull2 $rk2q1, $res0.2d, $h1.2d @ GHASH final block - high
pmull $t0.1q, $t0.1d, $h12k.1d @ GHASH final block - mid
eor $acc_hb, $acc_hb, $rk2 @ GHASH final block - high
eor $acc_lb, $acc_lb, $rk3 @ GHASH final block - low
eor $acc_mb, $acc_mb, $t0.16b @ GHASH final block - mid
movi $mod_constant.8b, #0xc2
eor $t9.16b, $acc_lb, $acc_hb @ MODULO - karatsuba tidy up
shl $mod_constantd, $mod_constantd, #56 @ mod_constant
eor $acc_mb, $acc_mb, $t9.16b @ MODULO - karatsuba tidy up
pmull $mod_t.1q, $acc_h.1d, $mod_constant.1d @ MODULO - top 64b align with mid
ext $acc_hb, $acc_hb, $acc_hb, #8 @ MODULO - other top alignment
eor $acc_mb, $acc_mb, $mod_t.16b @ MODULO - fold into mid
eor $acc_mb, $acc_mb, $acc_hb @ MODULO - fold into mid
pmull $mod_constant.1q, $acc_m.1d, $mod_constant.1d @ MODULO - mid 64b align with low
ext $acc_mb, $acc_mb, $acc_mb, #8 @ MODULO - other mid alignment
eor $acc_lb, $acc_lb, $mod_constant.16b @ MODULO - fold into low
stp $output_l0, $output_h0, [$output_ptr]
str $ctr32w, [$counter, #12] @ store the updated counter
eor $acc_lb, $acc_lb, $acc_mb @ MODULO - fold into low
ext $acc_lb, $acc_lb, $acc_lb, #8
rev64 $acc_lb, $acc_lb
mov x0, $len
st1 { $acc_l.16b }, [$current_tag]
ldp x21, x22, [sp, #16]
ldp x23, x24, [sp, #32]
ldp d8, d9, [sp, #48]
ldp d10, d11, [sp, #64]
ldp d12, d13, [sp, #80]
ldp d14, d15, [sp, #96]
ldp x19, x20, [sp], #112
ret
.L256_dec_ret:
mov w0, #0x0
ret
.size aes_gcm_dec_256_kernel,.-aes_gcm_dec_256_kernel
___
}
}
$code.=<<___;
.asciz "GHASH for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
#endif
___
if ($flavour =~ /64/) { ######## 64-bit code
sub unvmov {
my $arg=shift;
$arg =~ m/q([0-9]+)#(lo|hi),\s*q([0-9]+)#(lo|hi)/o &&
sprintf "ins v%d.d[%d],v%d.d[%d]",$1<8?$1:$1+8,($2 eq "lo")?0:1,
$3<8?$3:$3+8,($4 eq "lo")?0:1;
}
foreach(split("\n",$code)) {
s/@\s/\/\//o; # old->new style commentary
print $_,"\n";
}
} else { ######## 32-bit code
sub unvdup32 {
my $arg=shift;
$arg =~ m/q([0-9]+),\s*q([0-9]+)\[([0-3])\]/o &&
sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1;
}
sub unvpmullp64 {
my ($mnemonic,$arg)=@_;
if ($arg =~ m/q([0-9]+),\s*q([0-9]+),\s*q([0-9]+)/o) {
my $word = 0xf2a00e00|(($1&7)<<13)|(($1&8)<<19)
|(($2&7)<<17)|(($2&8)<<4)
|(($3&7)<<1) |(($3&8)<<2);
$word |= 0x00010001 if ($mnemonic =~ "2");
# since ARMv7 instructions are always encoded little-endian.
# correct solution is to use .inst directive, but older%%%%
# assemblers don't implement it:-(
sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s",
$word&0xff,($word>>8)&0xff,
($word>>16)&0xff,($word>>24)&0xff,
$mnemonic,$arg;
}
}
foreach(split("\n",$code)) {
s/\b[wx]([0-9]+)\b/r$1/go; # new->old registers
s/\bv([0-9])\.[12468]+[bsd]\b/q$1/go; # new->old registers
s/\/\/\s?/@ /o; # new->old style commentary
# fix up remaining new-style suffixes
s/\],#[0-9]+/]!/o;
s/cclr\s+([^,]+),\s*([a-z]+)/mov.$2 $1,#0/o or
s/vdup\.32\s+(.*)/unvdup32($1)/geo or
s/v?(pmull2?)\.p64\s+(.*)/unvpmullp64($1,$2)/geo or
s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or
s/^(\s+)b\./$1b/o or
s/^(\s+)ret/$1bx\tlr/o;
if (s/^(\s+)mov\.([a-z]+)/$1mov$2/) {
print " it $2\n";
}
-
+ s/__AARCH64E([BL])__/__ARME$1__/go;
print $_,"\n";
}
}
close STDOUT or die "error closing STDOUT: $!"; # enforce flush
diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c
index 01cde00e98b7..1a52000e6e9d 100644
--- a/crypto/objects/obj_dat.c
+++ b/crypto/objects/obj_dat.c
@@ -1,744 +1,763 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 "crypto/ctype.h"
#include <limits.h>
#include "internal/cryptlib.h"
#include <openssl/lhash.h>
#include <openssl/asn1.h>
#include "crypto/objects.h"
#include <openssl/bn.h>
#include "crypto/asn1.h"
#include "obj_local.h"
/* obj_dat.h is generated from objects.h by obj_dat.pl */
#include "obj_dat.h"
DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn);
DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, ln);
DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj);
#define ADDED_DATA 0
#define ADDED_SNAME 1
#define ADDED_LNAME 2
#define ADDED_NID 3
struct added_obj_st {
int type;
ASN1_OBJECT *obj;
};
static int new_nid = NUM_NID;
static LHASH_OF(ADDED_OBJ) *added = NULL;
static int sn_cmp(const ASN1_OBJECT *const *a, const unsigned int *b)
{
return strcmp((*a)->sn, nid_objs[*b].sn);
}
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn);
static int ln_cmp(const ASN1_OBJECT *const *a, const unsigned int *b)
{
return strcmp((*a)->ln, nid_objs[*b].ln);
}
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, ln);
static unsigned long added_obj_hash(const ADDED_OBJ *ca)
{
const ASN1_OBJECT *a;
int i;
unsigned long ret = 0;
unsigned char *p;
a = ca->obj;
switch (ca->type) {
case ADDED_DATA:
ret = a->length << 20L;
p = (unsigned char *)a->data;
for (i = 0; i < a->length; i++)
ret ^= p[i] << ((i * 3) % 24);
break;
case ADDED_SNAME:
ret = OPENSSL_LH_strhash(a->sn);
break;
case ADDED_LNAME:
ret = OPENSSL_LH_strhash(a->ln);
break;
case ADDED_NID:
ret = a->nid;
break;
default:
/* abort(); */
return 0;
}
ret &= 0x3fffffffL;
ret |= ((unsigned long)ca->type) << 30L;
return ret;
}
static int added_obj_cmp(const ADDED_OBJ *ca, const ADDED_OBJ *cb)
{
ASN1_OBJECT *a, *b;
int i;
i = ca->type - cb->type;
if (i)
return i;
a = ca->obj;
b = cb->obj;
switch (ca->type) {
case ADDED_DATA:
i = (a->length - b->length);
if (i)
return i;
return memcmp(a->data, b->data, (size_t)a->length);
case ADDED_SNAME:
if (a->sn == NULL)
return -1;
else if (b->sn == NULL)
return 1;
else
return strcmp(a->sn, b->sn);
case ADDED_LNAME:
if (a->ln == NULL)
return -1;
else if (b->ln == NULL)
return 1;
else
return strcmp(a->ln, b->ln);
case ADDED_NID:
return a->nid - b->nid;
default:
/* abort(); */
return 0;
}
}
static int init_added(void)
{
if (added != NULL)
return 1;
added = lh_ADDED_OBJ_new(added_obj_hash, added_obj_cmp);
return added != NULL;
}
static void cleanup1_doall(ADDED_OBJ *a)
{
a->obj->nid = 0;
a->obj->flags |= ASN1_OBJECT_FLAG_DYNAMIC |
ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | ASN1_OBJECT_FLAG_DYNAMIC_DATA;
}
static void cleanup2_doall(ADDED_OBJ *a)
{
a->obj->nid++;
}
static void cleanup3_doall(ADDED_OBJ *a)
{
if (--a->obj->nid == 0)
ASN1_OBJECT_free(a->obj);
OPENSSL_free(a);
}
void ossl_obj_cleanup_int(void)
{
if (added == NULL)
return;
lh_ADDED_OBJ_set_down_load(added, 0);
lh_ADDED_OBJ_doall(added, cleanup1_doall); /* zero counters */
lh_ADDED_OBJ_doall(added, cleanup2_doall); /* set counters */
lh_ADDED_OBJ_doall(added, cleanup3_doall); /* free objects */
lh_ADDED_OBJ_free(added);
added = NULL;
}
int OBJ_new_nid(int num)
{
int i;
i = new_nid;
new_nid += num;
return i;
}
int OBJ_add_object(const ASN1_OBJECT *obj)
{
ASN1_OBJECT *o;
ADDED_OBJ *ao[4] = { NULL, NULL, NULL, NULL }, *aop;
int i;
if (added == NULL)
if (!init_added())
return 0;
if ((o = OBJ_dup(obj)) == NULL)
goto err;
if ((ao[ADDED_NID] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
goto err2;
if ((o->length != 0) && (obj->data != NULL))
if ((ao[ADDED_DATA] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
goto err2;
if (o->sn != NULL)
if ((ao[ADDED_SNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
goto err2;
if (o->ln != NULL)
if ((ao[ADDED_LNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
goto err2;
for (i = ADDED_DATA; i <= ADDED_NID; i++) {
if (ao[i] != NULL) {
ao[i]->type = i;
ao[i]->obj = o;
aop = lh_ADDED_OBJ_insert(added, ao[i]);
/* memory leak, but should not normally matter */
OPENSSL_free(aop);
}
}
o->flags &=
~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
ASN1_OBJECT_FLAG_DYNAMIC_DATA);
return o->nid;
err2:
ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE);
err:
for (i = ADDED_DATA; i <= ADDED_NID; i++)
OPENSSL_free(ao[i]);
ASN1_OBJECT_free(o);
return NID_undef;
}
ASN1_OBJECT *OBJ_nid2obj(int n)
{
ADDED_OBJ ad, *adp;
ASN1_OBJECT ob;
if ((n >= 0) && (n < NUM_NID)) {
if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID);
return NULL;
}
return (ASN1_OBJECT *)&(nid_objs[n]);
}
/* Make sure we've loaded config before checking for any "added" objects */
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
if (added == NULL)
return NULL;
ad.type = ADDED_NID;
ad.obj = &ob;
ob.nid = n;
adp = lh_ADDED_OBJ_retrieve(added, &ad);
if (adp != NULL)
return adp->obj;
ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID);
return NULL;
}
const char *OBJ_nid2sn(int n)
{
ADDED_OBJ ad, *adp;
ASN1_OBJECT ob;
if ((n >= 0) && (n < NUM_NID)) {
if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID);
return NULL;
}
return nid_objs[n].sn;
}
/* Make sure we've loaded config before checking for any "added" objects */
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
if (added == NULL)
return NULL;
ad.type = ADDED_NID;
ad.obj = &ob;
ob.nid = n;
adp = lh_ADDED_OBJ_retrieve(added, &ad);
if (adp != NULL)
return adp->obj->sn;
ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID);
return NULL;
}
const char *OBJ_nid2ln(int n)
{
ADDED_OBJ ad, *adp;
ASN1_OBJECT ob;
if ((n >= 0) && (n < NUM_NID)) {
if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID);
return NULL;
}
return nid_objs[n].ln;
}
/* Make sure we've loaded config before checking for any "added" objects */
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
if (added == NULL)
return NULL;
ad.type = ADDED_NID;
ad.obj = &ob;
ob.nid = n;
adp = lh_ADDED_OBJ_retrieve(added, &ad);
if (adp != NULL)
return adp->obj->ln;
ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID);
return NULL;
}
static int obj_cmp(const ASN1_OBJECT *const *ap, const unsigned int *bp)
{
int j;
const ASN1_OBJECT *a = *ap;
const ASN1_OBJECT *b = &nid_objs[*bp];
j = (a->length - b->length);
if (j)
return j;
if (a->length == 0)
return 0;
return memcmp(a->data, b->data, a->length);
}
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj);
int OBJ_obj2nid(const ASN1_OBJECT *a)
{
const unsigned int *op;
ADDED_OBJ ad, *adp;
if (a == NULL)
return NID_undef;
if (a->nid != 0)
return a->nid;
if (a->length == 0)
return NID_undef;
/* Make sure we've loaded config before checking for any "added" objects */
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
if (added != NULL) {
ad.type = ADDED_DATA;
ad.obj = (ASN1_OBJECT *)a; /* XXX: ugly but harmless */
adp = lh_ADDED_OBJ_retrieve(added, &ad);
if (adp != NULL)
return adp->obj->nid;
}
op = OBJ_bsearch_obj(&a, obj_objs, NUM_OBJ);
if (op == NULL)
return NID_undef;
return nid_objs[*op].nid;
}
/*
* Convert an object name into an ASN1_OBJECT if "noname" is not set then
* search for short and long names first. This will convert the "dotted" form
* into an object: unlike OBJ_txt2nid it can be used with any objects, not
* just registered ones.
*/
ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name)
{
int nid = NID_undef;
ASN1_OBJECT *op;
unsigned char *buf;
unsigned char *p;
const unsigned char *cp;
int i, j;
if (!no_name) {
if (((nid = OBJ_sn2nid(s)) != NID_undef) ||
((nid = OBJ_ln2nid(s)) != NID_undef))
return OBJ_nid2obj(nid);
if (!ossl_isdigit(*s)) {
ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_OBJECT_NAME);
return NULL;
}
}
/* Work out size of content octets */
i = a2d_ASN1_OBJECT(NULL, 0, s, -1);
if (i <= 0) {
/* Don't clear the error */
/*
* ERR_clear_error();
*/
return NULL;
}
/* Work out total size */
j = ASN1_object_size(0, i, V_ASN1_OBJECT);
if (j < 0)
return NULL;
if ((buf = OPENSSL_malloc(j)) == NULL) {
ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE);
return NULL;
}
p = buf;
/* Write out tag+length */
ASN1_put_object(&p, 0, i, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
/* Write out contents */
a2d_ASN1_OBJECT(p, i, s, -1);
cp = buf;
op = d2i_ASN1_OBJECT(NULL, &cp, j);
OPENSSL_free(buf);
return op;
}
int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
{
int i, n = 0, len, nid, first, use_bn;
BIGNUM *bl;
unsigned long l;
const unsigned char *p;
char tbuf[DECIMAL_SIZE(i) + DECIMAL_SIZE(l) + 2];
/* Ensure that, at every state, |buf| is NUL-terminated. */
if (buf && buf_len > 0)
buf[0] = '\0';
if ((a == NULL) || (a->data == NULL))
return 0;
if (!no_name && (nid = OBJ_obj2nid(a)) != NID_undef) {
const char *s;
s = OBJ_nid2ln(nid);
if (s == NULL)
s = OBJ_nid2sn(nid);
if (s) {
if (buf)
OPENSSL_strlcpy(buf, s, buf_len);
n = strlen(s);
return n;
}
}
len = a->length;
p = a->data;
first = 1;
bl = NULL;
+ /*
+ * RFC 2578 (STD 58) says this about OBJECT IDENTIFIERs:
+ *
+ * > 3.5. OBJECT IDENTIFIER values
+ * >
+ * > An OBJECT IDENTIFIER value is an ordered list of non-negative
+ * > numbers. For the SMIv2, each number in the list is referred to as a
+ * > sub-identifier, there are at most 128 sub-identifiers in a value,
+ * > and each sub-identifier has a maximum value of 2^32-1 (4294967295
+ * > decimal).
+ *
+ * So a legitimate OID according to this RFC is at most (32 * 128 / 7),
+ * i.e. 586 bytes long.
+ *
+ * Ref: https://datatracker.ietf.org/doc/html/rfc2578#section-3.5
+ */
+ if (len > 586)
+ goto err;
+
while (len > 0) {
l = 0;
use_bn = 0;
for (;;) {
unsigned char c = *p++;
len--;
if ((len == 0) && (c & 0x80))
goto err;
if (use_bn) {
if (!BN_add_word(bl, c & 0x7f))
goto err;
} else
l |= c & 0x7f;
if (!(c & 0x80))
break;
if (!use_bn && (l > (ULONG_MAX >> 7L))) {
if (bl == NULL && (bl = BN_new()) == NULL)
goto err;
if (!BN_set_word(bl, l))
goto err;
use_bn = 1;
}
if (use_bn) {
if (!BN_lshift(bl, bl, 7))
goto err;
} else
l <<= 7L;
}
if (first) {
first = 0;
if (l >= 80) {
i = 2;
if (use_bn) {
if (!BN_sub_word(bl, 80))
goto err;
} else
l -= 80;
} else {
i = (int)(l / 40);
l -= (long)(i * 40);
}
if (buf && (buf_len > 1)) {
*buf++ = i + '0';
*buf = '\0';
buf_len--;
}
n++;
}
if (use_bn) {
char *bndec;
bndec = BN_bn2dec(bl);
if (!bndec)
goto err;
i = strlen(bndec);
if (buf) {
if (buf_len > 1) {
*buf++ = '.';
*buf = '\0';
buf_len--;
}
OPENSSL_strlcpy(buf, bndec, buf_len);
if (i > buf_len) {
buf += buf_len;
buf_len = 0;
} else {
buf += i;
buf_len -= i;
}
}
n++;
n += i;
OPENSSL_free(bndec);
} else {
BIO_snprintf(tbuf, sizeof(tbuf), ".%lu", l);
i = strlen(tbuf);
if (buf && (buf_len > 0)) {
OPENSSL_strlcpy(buf, tbuf, buf_len);
if (i > buf_len) {
buf += buf_len;
buf_len = 0;
} else {
buf += i;
buf_len -= i;
}
}
n += i;
l = 0;
}
}
BN_free(bl);
return n;
err:
BN_free(bl);
return -1;
}
int OBJ_txt2nid(const char *s)
{
ASN1_OBJECT *obj;
int nid;
obj = OBJ_txt2obj(s, 0);
nid = OBJ_obj2nid(obj);
ASN1_OBJECT_free(obj);
return nid;
}
int OBJ_ln2nid(const char *s)
{
ASN1_OBJECT o;
const ASN1_OBJECT *oo = &o;
ADDED_OBJ ad, *adp;
const unsigned int *op;
/* Make sure we've loaded config before checking for any "added" objects */
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
o.ln = s;
if (added != NULL) {
ad.type = ADDED_LNAME;
ad.obj = &o;
adp = lh_ADDED_OBJ_retrieve(added, &ad);
if (adp != NULL)
return adp->obj->nid;
}
op = OBJ_bsearch_ln(&oo, ln_objs, NUM_LN);
if (op == NULL)
return NID_undef;
return nid_objs[*op].nid;
}
int OBJ_sn2nid(const char *s)
{
ASN1_OBJECT o;
const ASN1_OBJECT *oo = &o;
ADDED_OBJ ad, *adp;
const unsigned int *op;
/* Make sure we've loaded config before checking for any "added" objects */
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
o.sn = s;
if (added != NULL) {
ad.type = ADDED_SNAME;
ad.obj = &o;
adp = lh_ADDED_OBJ_retrieve(added, &ad);
if (adp != NULL)
return adp->obj->nid;
}
op = OBJ_bsearch_sn(&oo, sn_objs, NUM_SN);
if (op == NULL)
return NID_undef;
return nid_objs[*op].nid;
}
const void *OBJ_bsearch_(const void *key, const void *base, int num, int size,
int (*cmp) (const void *, const void *))
{
return OBJ_bsearch_ex_(key, base, num, size, cmp, 0);
}
const void *OBJ_bsearch_ex_(const void *key, const void *base, int num,
int size,
int (*cmp) (const void *, const void *),
int flags)
{
const char *p = ossl_bsearch(key, base, num, size, cmp, flags);
#ifdef CHARSET_EBCDIC
/*
* THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and I
* don't have perl (yet), we revert to a *LINEAR* search when the object
* wasn't found in the binary search.
*/
if (p == NULL) {
const char *base_ = base;
int l, h, i = 0, c = 0;
for (i = 0; i < num; ++i) {
p = &(base_[i * size]);
c = (*cmp) (key, p);
if (c == 0
|| (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
return p;
}
}
#endif
return p;
}
/*
* Parse a BIO sink to create some extra oid's objects.
* Line format:<OID:isdigit or '.']><isspace><SN><isspace><LN>
*/
int OBJ_create_objects(BIO *in)
{
char buf[512];
int i, num = 0;
char *o, *s, *l = NULL;
for (;;) {
s = o = NULL;
i = BIO_gets(in, buf, 512);
if (i <= 0)
return num;
buf[i - 1] = '\0';
if (!ossl_isalnum(buf[0]))
return num;
o = s = buf;
while (ossl_isdigit(*s) || *s == '.')
s++;
if (*s != '\0') {
*(s++) = '\0';
while (ossl_isspace(*s))
s++;
if (*s == '\0') {
s = NULL;
} else {
l = s;
while (*l != '\0' && !ossl_isspace(*l))
l++;
if (*l != '\0') {
*(l++) = '\0';
while (ossl_isspace(*l))
l++;
if (*l == '\0') {
l = NULL;
}
} else {
l = NULL;
}
}
} else {
s = NULL;
}
if (*o == '\0')
return num;
if (!OBJ_create(o, s, l))
return num;
num++;
}
}
int OBJ_create(const char *oid, const char *sn, const char *ln)
{
ASN1_OBJECT *tmpoid = NULL;
int ok = 0;
/* Check to see if short or long name already present */
if ((sn != NULL && OBJ_sn2nid(sn) != NID_undef)
|| (ln != NULL && OBJ_ln2nid(ln) != NID_undef)) {
ERR_raise(ERR_LIB_OBJ, OBJ_R_OID_EXISTS);
return 0;
}
/* Convert numerical OID string to an ASN1_OBJECT structure */
tmpoid = OBJ_txt2obj(oid, 1);
if (tmpoid == NULL)
return 0;
/* If NID is not NID_undef then object already exists */
if (OBJ_obj2nid(tmpoid) != NID_undef) {
ERR_raise(ERR_LIB_OBJ, OBJ_R_OID_EXISTS);
goto err;
}
tmpoid->nid = OBJ_new_nid(1);
if (tmpoid->nid == NID_undef)
goto err;
tmpoid->sn = (char *)sn;
tmpoid->ln = (char *)ln;
ok = OBJ_add_object(tmpoid);
tmpoid->sn = NULL;
tmpoid->ln = NULL;
err:
ASN1_OBJECT_free(tmpoid);
return ok;
}
size_t OBJ_length(const ASN1_OBJECT *obj)
{
if (obj == NULL)
return 0;
return obj->length;
}
const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj)
{
if (obj == NULL)
return NULL;
return obj->data;
}
diff --git a/crypto/property/property.c b/crypto/property/property.c
index 844c25cee936..b97861d4862f 100644
--- a/crypto/property/property.c
+++ b/crypto/property/property.c
@@ -1,769 +1,770 @@
/*
- * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <openssl/crypto.h>
#include "internal/core.h"
#include "internal/property.h"
#include "internal/provider.h"
#include "internal/tsan_assist.h"
#include "crypto/ctype.h"
#include <openssl/lhash.h>
#include <openssl/rand.h>
#include "internal/thread_once.h"
#include "crypto/lhash.h"
#include "crypto/sparse_array.h"
#include "property_local.h"
/*
* The number of elements in the query cache before we initiate a flush.
* If reducing this, also ensure the stochastic test in test/property_test.c
* isn't likely to fail.
*/
#define IMPL_CACHE_FLUSH_THRESHOLD 500
typedef struct {
void *method;
int (*up_ref)(void *);
void (*free)(void *);
} METHOD;
typedef struct {
const OSSL_PROVIDER *provider;
OSSL_PROPERTY_LIST *properties;
METHOD method;
} IMPLEMENTATION;
DEFINE_STACK_OF(IMPLEMENTATION)
typedef struct {
const OSSL_PROVIDER *provider;
const char *query;
METHOD method;
char body[1];
} QUERY;
DEFINE_LHASH_OF(QUERY);
typedef struct {
int nid;
STACK_OF(IMPLEMENTATION) *impls;
LHASH_OF(QUERY) *cache;
} ALGORITHM;
struct ossl_method_store_st {
OSSL_LIB_CTX *ctx;
SPARSE_ARRAY_OF(ALGORITHM) *algs;
/*
* Lock to protect the |algs| array from concurrent writing, when
* individual implementations or queries are inserted. This is used
* by the appropriate functions here.
*/
CRYPTO_RWLOCK *lock;
/*
* Lock to reserve the whole store. This is used when fetching a set
* of algorithms, via these functions, found in crypto/core_fetch.c:
* ossl_method_construct_reserve_store()
* ossl_method_construct_unreserve_store()
*/
CRYPTO_RWLOCK *biglock;
/* query cache specific values */
/* Count of the query cache entries for all algs */
size_t cache_nelem;
/* Flag: 1 if query cache entries for all algs need flushing */
int cache_need_flush;
};
typedef struct {
LHASH_OF(QUERY) *cache;
size_t nelem;
uint32_t seed;
unsigned char using_global_seed;
} IMPL_CACHE_FLUSH;
DEFINE_SPARSE_ARRAY_OF(ALGORITHM);
typedef struct ossl_global_properties_st {
OSSL_PROPERTY_LIST *list;
#ifndef FIPS_MODULE
unsigned int no_mirrored : 1;
#endif
} OSSL_GLOBAL_PROPERTIES;
static void ossl_method_cache_flush_alg(OSSL_METHOD_STORE *store,
ALGORITHM *alg);
static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid);
/* Global properties are stored per library context */
static void ossl_ctx_global_properties_free(void *vglobp)
{
OSSL_GLOBAL_PROPERTIES *globp = vglobp;
if (globp != NULL) {
ossl_property_free(globp->list);
OPENSSL_free(globp);
}
}
static void *ossl_ctx_global_properties_new(OSSL_LIB_CTX *ctx)
{
return OPENSSL_zalloc(sizeof(OSSL_GLOBAL_PROPERTIES));
}
static const OSSL_LIB_CTX_METHOD ossl_ctx_global_properties_method = {
OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
ossl_ctx_global_properties_new,
ossl_ctx_global_properties_free,
};
OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *libctx,
int loadconfig)
{
OSSL_GLOBAL_PROPERTIES *globp;
#ifndef FIPS_MODULE
if (loadconfig && !OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL))
return NULL;
#endif
globp = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
&ossl_ctx_global_properties_method);
return globp != NULL ? &globp->list : NULL;
}
#ifndef FIPS_MODULE
int ossl_global_properties_no_mirrored(OSSL_LIB_CTX *libctx)
{
OSSL_GLOBAL_PROPERTIES *globp
= ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
&ossl_ctx_global_properties_method);
return globp != NULL && globp->no_mirrored ? 1 : 0;
}
void ossl_global_properties_stop_mirroring(OSSL_LIB_CTX *libctx)
{
OSSL_GLOBAL_PROPERTIES *globp
= ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
&ossl_ctx_global_properties_method);
if (globp != NULL)
globp->no_mirrored = 1;
}
#endif
static int ossl_method_up_ref(METHOD *method)
{
return (*method->up_ref)(method->method);
}
static void ossl_method_free(METHOD *method)
{
(*method->free)(method->method);
}
static __owur int ossl_property_read_lock(OSSL_METHOD_STORE *p)
{
return p != NULL ? CRYPTO_THREAD_read_lock(p->lock) : 0;
}
static __owur int ossl_property_write_lock(OSSL_METHOD_STORE *p)
{
return p != NULL ? CRYPTO_THREAD_write_lock(p->lock) : 0;
}
static int ossl_property_unlock(OSSL_METHOD_STORE *p)
{
return p != 0 ? CRYPTO_THREAD_unlock(p->lock) : 0;
}
static unsigned long query_hash(const QUERY *a)
{
return OPENSSL_LH_strhash(a->query);
}
static int query_cmp(const QUERY *a, const QUERY *b)
{
int res = strcmp(a->query, b->query);
if (res == 0 && a->provider != NULL && b->provider != NULL)
res = b->provider > a->provider ? 1
: b->provider < a->provider ? -1
: 0;
return res;
}
static void impl_free(IMPLEMENTATION *impl)
{
if (impl != NULL) {
ossl_method_free(&impl->method);
OPENSSL_free(impl);
}
}
static void impl_cache_free(QUERY *elem)
{
if (elem != NULL) {
ossl_method_free(&elem->method);
OPENSSL_free(elem);
}
}
static void impl_cache_flush_alg(ossl_uintmax_t idx, ALGORITHM *alg)
{
lh_QUERY_doall(alg->cache, &impl_cache_free);
lh_QUERY_flush(alg->cache);
}
static void alg_cleanup(ossl_uintmax_t idx, ALGORITHM *a, void *arg)
{
OSSL_METHOD_STORE *store = arg;
if (a != NULL) {
sk_IMPLEMENTATION_pop_free(a->impls, &impl_free);
lh_QUERY_doall(a->cache, &impl_cache_free);
lh_QUERY_free(a->cache);
OPENSSL_free(a);
}
if (store != NULL)
ossl_sa_ALGORITHM_set(store->algs, idx, NULL);
}
/*
* The OSSL_LIB_CTX param here allows access to underlying property data needed
* for computation
*/
OSSL_METHOD_STORE *ossl_method_store_new(OSSL_LIB_CTX *ctx)
{
OSSL_METHOD_STORE *res;
res = OPENSSL_zalloc(sizeof(*res));
if (res != NULL) {
res->ctx = ctx;
if ((res->algs = ossl_sa_ALGORITHM_new()) == NULL
|| (res->lock = CRYPTO_THREAD_lock_new()) == NULL
|| (res->biglock = CRYPTO_THREAD_lock_new()) == NULL) {
ossl_method_store_free(res);
return NULL;
}
}
return res;
}
void ossl_method_store_free(OSSL_METHOD_STORE *store)
{
if (store != NULL) {
if (store->algs != NULL)
ossl_sa_ALGORITHM_doall_arg(store->algs, &alg_cleanup, store);
ossl_sa_ALGORITHM_free(store->algs);
CRYPTO_THREAD_lock_free(store->lock);
CRYPTO_THREAD_lock_free(store->biglock);
OPENSSL_free(store);
}
}
int ossl_method_lock_store(OSSL_METHOD_STORE *store)
{
return store != NULL ? CRYPTO_THREAD_write_lock(store->biglock) : 0;
}
int ossl_method_unlock_store(OSSL_METHOD_STORE *store)
{
return store != NULL ? CRYPTO_THREAD_unlock(store->biglock) : 0;
}
static ALGORITHM *ossl_method_store_retrieve(OSSL_METHOD_STORE *store, int nid)
{
return ossl_sa_ALGORITHM_get(store->algs, nid);
}
static int ossl_method_store_insert(OSSL_METHOD_STORE *store, ALGORITHM *alg)
{
return ossl_sa_ALGORITHM_set(store->algs, alg->nid, alg);
}
int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov,
int nid, const char *properties, void *method,
int (*method_up_ref)(void *),
void (*method_destruct)(void *))
{
ALGORITHM *alg = NULL;
IMPLEMENTATION *impl;
int ret = 0;
int i;
if (nid <= 0 || method == NULL || store == NULL)
return 0;
if (properties == NULL)
properties = "";
if (!ossl_assert(prov != NULL))
return 0;
/* Create new entry */
impl = OPENSSL_malloc(sizeof(*impl));
if (impl == NULL)
return 0;
impl->method.method = method;
impl->method.up_ref = method_up_ref;
impl->method.free = method_destruct;
if (!ossl_method_up_ref(&impl->method)) {
OPENSSL_free(impl);
return 0;
}
impl->provider = prov;
/* Insert into the hash table if required */
if (!ossl_property_write_lock(store)) {
OPENSSL_free(impl);
return 0;
}
ossl_method_cache_flush(store, nid);
if ((impl->properties = ossl_prop_defn_get(store->ctx, properties)) == NULL) {
impl->properties = ossl_parse_property(store->ctx, properties);
if (impl->properties == NULL)
goto err;
if (!ossl_prop_defn_set(store->ctx, properties, &impl->properties)) {
ossl_property_free(impl->properties);
impl->properties = NULL;
goto err;
}
}
alg = ossl_method_store_retrieve(store, nid);
if (alg == NULL) {
if ((alg = OPENSSL_zalloc(sizeof(*alg))) == NULL
|| (alg->impls = sk_IMPLEMENTATION_new_null()) == NULL
|| (alg->cache = lh_QUERY_new(&query_hash, &query_cmp)) == NULL)
goto err;
alg->nid = nid;
if (!ossl_method_store_insert(store, alg))
goto err;
}
/* Push onto stack if there isn't one there already */
for (i = 0; i < sk_IMPLEMENTATION_num(alg->impls); i++) {
const IMPLEMENTATION *tmpimpl = sk_IMPLEMENTATION_value(alg->impls, i);
if (tmpimpl->provider == impl->provider
&& tmpimpl->properties == impl->properties)
break;
}
if (i == sk_IMPLEMENTATION_num(alg->impls)
&& sk_IMPLEMENTATION_push(alg->impls, impl))
ret = 1;
ossl_property_unlock(store);
if (ret == 0)
impl_free(impl);
return ret;
err:
ossl_property_unlock(store);
alg_cleanup(0, alg, NULL);
impl_free(impl);
return 0;
}
int ossl_method_store_remove(OSSL_METHOD_STORE *store, int nid,
const void *method)
{
ALGORITHM *alg = NULL;
int i;
if (nid <= 0 || method == NULL || store == NULL)
return 0;
if (!ossl_property_write_lock(store))
return 0;
ossl_method_cache_flush(store, nid);
alg = ossl_method_store_retrieve(store, nid);
if (alg == NULL) {
ossl_property_unlock(store);
return 0;
}
/*
* A sorting find then a delete could be faster but these stacks should be
* relatively small, so we avoid the overhead. Sorting could also surprise
* users when result orderings change (even though they are not guaranteed).
*/
for (i = 0; i < sk_IMPLEMENTATION_num(alg->impls); i++) {
IMPLEMENTATION *impl = sk_IMPLEMENTATION_value(alg->impls, i);
if (impl->method.method == method) {
impl_free(impl);
(void)sk_IMPLEMENTATION_delete(alg->impls, i);
ossl_property_unlock(store);
return 1;
}
}
ossl_property_unlock(store);
return 0;
}
struct alg_cleanup_by_provider_data_st {
OSSL_METHOD_STORE *store;
const OSSL_PROVIDER *prov;
};
static void
alg_cleanup_by_provider(ossl_uintmax_t idx, ALGORITHM *alg, void *arg)
{
struct alg_cleanup_by_provider_data_st *data = arg;
int i, count;
/*
* We walk the stack backwards, to avoid having to deal with stack shifts
* caused by deletion
*/
for (count = 0, i = sk_IMPLEMENTATION_num(alg->impls); i-- > 0;) {
IMPLEMENTATION *impl = sk_IMPLEMENTATION_value(alg->impls, i);
if (impl->provider == data->prov) {
impl_free(impl);
(void)sk_IMPLEMENTATION_delete(alg->impls, i);
count++;
}
}
/*
* If we removed any implementation, we also clear the whole associated
* cache, 'cause that's the sensible thing to do.
* There's no point flushing the cache entries where we didn't remove
* any implementation, though.
*/
if (count > 0)
ossl_method_cache_flush_alg(data->store, alg);
}
int ossl_method_store_remove_all_provided(OSSL_METHOD_STORE *store,
const OSSL_PROVIDER *prov)
{
struct alg_cleanup_by_provider_data_st data;
if (!ossl_property_write_lock(store))
return 0;
data.prov = prov;
data.store = store;
ossl_sa_ALGORITHM_doall_arg(store->algs, &alg_cleanup_by_provider, &data);
ossl_property_unlock(store);
return 1;
}
static void alg_do_one(ALGORITHM *alg, IMPLEMENTATION *impl,
void (*fn)(int id, void *method, void *fnarg),
void *fnarg)
{
fn(alg->nid, impl->method.method, fnarg);
}
struct alg_do_each_data_st {
void (*fn)(int id, void *method, void *fnarg);
void *fnarg;
};
static void alg_do_each(ossl_uintmax_t idx, ALGORITHM *alg, void *arg)
{
struct alg_do_each_data_st *data = arg;
int i, end = sk_IMPLEMENTATION_num(alg->impls);
for (i = 0; i < end; i++) {
IMPLEMENTATION *impl = sk_IMPLEMENTATION_value(alg->impls, i);
alg_do_one(alg, impl, data->fn, data->fnarg);
}
}
void ossl_method_store_do_all(OSSL_METHOD_STORE *store,
void (*fn)(int id, void *method, void *fnarg),
void *fnarg)
{
struct alg_do_each_data_st data;
data.fn = fn;
data.fnarg = fnarg;
if (store != NULL)
ossl_sa_ALGORITHM_doall_arg(store->algs, alg_do_each, &data);
}
int ossl_method_store_fetch(OSSL_METHOD_STORE *store,
int nid, const char *prop_query,
const OSSL_PROVIDER **prov_rw, void **method)
{
OSSL_PROPERTY_LIST **plp;
ALGORITHM *alg;
IMPLEMENTATION *impl, *best_impl = NULL;
OSSL_PROPERTY_LIST *pq = NULL, *p2 = NULL;
const OSSL_PROVIDER *prov = prov_rw != NULL ? *prov_rw : NULL;
int ret = 0;
int j, best = -1, score, optional;
-#ifndef FIPS_MODULE
- if (!OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL))
+ if (nid <= 0 || method == NULL || store == NULL)
return 0;
-#endif
- if (nid <= 0 || method == NULL || store == NULL)
+#ifndef FIPS_MODULE
+ if (ossl_lib_ctx_is_default(store->ctx)
+ && !OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL))
return 0;
+#endif
/* This only needs to be a read lock, because the query won't create anything */
if (!ossl_property_read_lock(store))
return 0;
alg = ossl_method_store_retrieve(store, nid);
if (alg == NULL) {
ossl_property_unlock(store);
return 0;
}
if (prop_query != NULL)
p2 = pq = ossl_parse_query(store->ctx, prop_query, 0);
plp = ossl_ctx_global_properties(store->ctx, 0);
if (plp != NULL && *plp != NULL) {
if (pq == NULL) {
pq = *plp;
} else {
p2 = ossl_property_merge(pq, *plp);
ossl_property_free(pq);
if (p2 == NULL)
goto fin;
pq = p2;
}
}
if (pq == NULL) {
for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) {
if ((impl = sk_IMPLEMENTATION_value(alg->impls, j)) != NULL
&& (prov == NULL || impl->provider == prov)) {
best_impl = impl;
ret = 1;
break;
}
}
goto fin;
}
optional = ossl_property_has_optional(pq);
for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) {
if ((impl = sk_IMPLEMENTATION_value(alg->impls, j)) != NULL
&& (prov == NULL || impl->provider == prov)) {
score = ossl_property_match_count(pq, impl->properties);
if (score > best) {
best_impl = impl;
best = score;
ret = 1;
if (!optional)
goto fin;
}
}
}
fin:
if (ret && ossl_method_up_ref(&best_impl->method)) {
*method = best_impl->method.method;
if (prov_rw != NULL)
*prov_rw = best_impl->provider;
} else {
ret = 0;
}
ossl_property_unlock(store);
ossl_property_free(p2);
return ret;
}
static void ossl_method_cache_flush_alg(OSSL_METHOD_STORE *store,
ALGORITHM *alg)
{
store->cache_nelem -= lh_QUERY_num_items(alg->cache);
impl_cache_flush_alg(0, alg);
}
static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid)
{
ALGORITHM *alg = ossl_method_store_retrieve(store, nid);
if (alg != NULL)
ossl_method_cache_flush_alg(store, alg);
}
int ossl_method_store_cache_flush_all(OSSL_METHOD_STORE *store)
{
if (!ossl_property_write_lock(store))
return 0;
ossl_sa_ALGORITHM_doall(store->algs, &impl_cache_flush_alg);
store->cache_nelem = 0;
ossl_property_unlock(store);
return 1;
}
IMPLEMENT_LHASH_DOALL_ARG(QUERY, IMPL_CACHE_FLUSH);
/*
* Flush an element from the query cache (perhaps).
*
* In order to avoid taking a write lock or using atomic operations
* to keep accurate least recently used (LRU) or least frequently used
* (LFU) information, the procedure used here is to stochastically
* flush approximately half the cache.
*
* This procedure isn't ideal, LRU or LFU would be better. However,
* in normal operation, reaching a full cache would be unexpected.
* It means that no steady state of algorithm queries has been reached.
* That is, it is most likely an attack of some form. A suboptimal clearance
* strategy that doesn't degrade performance of the normal case is
* preferable to a more refined approach that imposes a performance
* impact.
*/
static void impl_cache_flush_cache(QUERY *c, IMPL_CACHE_FLUSH *state)
{
uint32_t n;
/*
* Implement the 32 bit xorshift as suggested by George Marsaglia in:
* https://doi.org/10.18637/jss.v008.i14
*
* This is a very fast PRNG so there is no need to extract bits one at a
* time and use the entire value each time.
*/
n = state->seed;
n ^= n << 13;
n ^= n >> 17;
n ^= n << 5;
state->seed = n;
if ((n & 1) != 0)
impl_cache_free(lh_QUERY_delete(state->cache, c));
else
state->nelem++;
}
static void impl_cache_flush_one_alg(ossl_uintmax_t idx, ALGORITHM *alg,
void *v)
{
IMPL_CACHE_FLUSH *state = (IMPL_CACHE_FLUSH *)v;
state->cache = alg->cache;
lh_QUERY_doall_IMPL_CACHE_FLUSH(state->cache, &impl_cache_flush_cache,
state);
}
static void ossl_method_cache_flush_some(OSSL_METHOD_STORE *store)
{
IMPL_CACHE_FLUSH state;
static TSAN_QUALIFIER uint32_t global_seed = 1;
state.nelem = 0;
state.using_global_seed = 0;
if ((state.seed = OPENSSL_rdtsc()) == 0) {
/* If there is no timer available, seed another way */
state.using_global_seed = 1;
state.seed = tsan_load(&global_seed);
}
store->cache_need_flush = 0;
ossl_sa_ALGORITHM_doall_arg(store->algs, &impl_cache_flush_one_alg, &state);
store->cache_nelem = state.nelem;
/* Without a timer, update the global seed */
if (state.using_global_seed)
tsan_store(&global_seed, state.seed);
}
int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
int nid, const char *prop_query, void **method)
{
ALGORITHM *alg;
QUERY elem, *r;
int res = 0;
if (nid <= 0 || store == NULL || prop_query == NULL)
return 0;
if (!ossl_property_read_lock(store))
return 0;
alg = ossl_method_store_retrieve(store, nid);
if (alg == NULL)
goto err;
elem.query = prop_query;
elem.provider = prov;
r = lh_QUERY_retrieve(alg->cache, &elem);
if (r == NULL)
goto err;
if (ossl_method_up_ref(&r->method)) {
*method = r->method.method;
res = 1;
}
err:
ossl_property_unlock(store);
return res;
}
int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
int nid, const char *prop_query, void *method,
int (*method_up_ref)(void *),
void (*method_destruct)(void *))
{
QUERY elem, *old, *p = NULL;
ALGORITHM *alg;
size_t len;
int res = 1;
if (nid <= 0 || store == NULL || prop_query == NULL)
return 0;
if (!ossl_assert(prov != NULL))
return 0;
if (!ossl_property_write_lock(store))
return 0;
if (store->cache_need_flush)
ossl_method_cache_flush_some(store);
alg = ossl_method_store_retrieve(store, nid);
if (alg == NULL)
goto err;
if (method == NULL) {
elem.query = prop_query;
elem.provider = prov;
if ((old = lh_QUERY_delete(alg->cache, &elem)) != NULL) {
impl_cache_free(old);
store->cache_nelem--;
}
goto end;
}
p = OPENSSL_malloc(sizeof(*p) + (len = strlen(prop_query)));
if (p != NULL) {
p->query = p->body;
p->provider = prov;
p->method.method = method;
p->method.up_ref = method_up_ref;
p->method.free = method_destruct;
if (!ossl_method_up_ref(&p->method))
goto err;
memcpy((char *)p->query, prop_query, len + 1);
if ((old = lh_QUERY_insert(alg->cache, p)) != NULL) {
impl_cache_free(old);
goto end;
}
if (!lh_QUERY_error(alg->cache)) {
if (++store->cache_nelem >= IMPL_CACHE_FLUSH_THRESHOLD)
store->cache_need_flush = 1;
goto end;
}
ossl_method_free(&p->method);
}
err:
res = 0;
OPENSSL_free(p);
end:
ossl_property_unlock(store);
return res;
}
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index f341d915db76..0fcf4fe3bc1e 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -1,844 +1,850 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/* We need to use some engine deprecated APIs */
#define OPENSSL_SUPPRESS_DEPRECATED
#include <openssl/err.h>
#include <openssl/opensslconf.h>
#include <openssl/core_names.h>
#include "internal/cryptlib.h"
#include "internal/thread_once.h"
#include "crypto/rand.h"
#include "crypto/cryptlib.h"
#include "rand_local.h"
#ifndef FIPS_MODULE
# include <stdio.h>
# include <time.h>
# include <limits.h>
# include <openssl/conf.h>
# include <openssl/trace.h>
# include <openssl/engine.h>
# include "crypto/rand_pool.h"
# include "prov/seeding.h"
# include "e_os.h"
# ifndef OPENSSL_NO_ENGINE
/* non-NULL if default_RAND_meth is ENGINE-provided */
static ENGINE *funct_ref;
static CRYPTO_RWLOCK *rand_engine_lock;
# endif
# ifndef OPENSSL_NO_DEPRECATED_3_0
static CRYPTO_RWLOCK *rand_meth_lock;
static const RAND_METHOD *default_RAND_meth;
# endif
static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;
static int rand_inited = 0;
DEFINE_RUN_ONCE_STATIC(do_rand_init)
{
# ifndef OPENSSL_NO_ENGINE
rand_engine_lock = CRYPTO_THREAD_lock_new();
if (rand_engine_lock == NULL)
return 0;
# endif
# ifndef OPENSSL_NO_DEPRECATED_3_0
rand_meth_lock = CRYPTO_THREAD_lock_new();
if (rand_meth_lock == NULL)
goto err;
# endif
if (!ossl_rand_pool_init())
goto err;
rand_inited = 1;
return 1;
err:
# ifndef OPENSSL_NO_DEPRECATED_3_0
CRYPTO_THREAD_lock_free(rand_meth_lock);
rand_meth_lock = NULL;
# endif
# ifndef OPENSSL_NO_ENGINE
CRYPTO_THREAD_lock_free(rand_engine_lock);
rand_engine_lock = NULL;
# endif
return 0;
}
void ossl_rand_cleanup_int(void)
{
# ifndef OPENSSL_NO_DEPRECATED_3_0
const RAND_METHOD *meth = default_RAND_meth;
if (!rand_inited)
return;
if (meth != NULL && meth->cleanup != NULL)
meth->cleanup();
RAND_set_rand_method(NULL);
# endif
ossl_rand_pool_cleanup();
# ifndef OPENSSL_NO_ENGINE
CRYPTO_THREAD_lock_free(rand_engine_lock);
rand_engine_lock = NULL;
# endif
# ifndef OPENSSL_NO_DEPRECATED_3_0
CRYPTO_THREAD_lock_free(rand_meth_lock);
rand_meth_lock = NULL;
# endif
ossl_release_default_drbg_ctx();
rand_inited = 0;
}
/*
* RAND_close_seed_files() ensures that any seed file descriptors are
* closed after use. This only applies to libcrypto/default provider,
* it does not apply to other providers.
*/
void RAND_keep_random_devices_open(int keep)
{
if (RUN_ONCE(&rand_init, do_rand_init))
ossl_rand_pool_keep_random_devices_open(keep);
}
/*
* RAND_poll() reseeds the default RNG using random input
*
* The random input is obtained from polling various entropy
* sources which depend on the operating system and are
* configurable via the --with-rand-seed configure option.
*/
int RAND_poll(void)
{
# ifndef OPENSSL_NO_DEPRECATED_3_0
const RAND_METHOD *meth = RAND_get_rand_method();
int ret = meth == RAND_OpenSSL();
if (meth == NULL)
return 0;
if (!ret) {
/* fill random pool and seed the current legacy RNG */
RAND_POOL *pool = ossl_rand_pool_new(RAND_DRBG_STRENGTH, 1,
(RAND_DRBG_STRENGTH + 7) / 8,
RAND_POOL_MAX_LENGTH);
if (pool == NULL)
return 0;
if (ossl_pool_acquire_entropy(pool) == 0)
goto err;
if (meth->add == NULL
|| meth->add(ossl_rand_pool_buffer(pool),
ossl_rand_pool_length(pool),
(ossl_rand_pool_entropy(pool) / 8.0)) == 0)
goto err;
ret = 1;
err:
ossl_rand_pool_free(pool);
}
return ret;
# else
static const char salt[] = "polling";
RAND_seed(salt, sizeof(salt));
return 1;
# endif
}
# ifndef OPENSSL_NO_DEPRECATED_3_0
static int rand_set_rand_method_internal(const RAND_METHOD *meth,
ossl_unused ENGINE *e)
{
if (!RUN_ONCE(&rand_init, do_rand_init))
return 0;
if (!CRYPTO_THREAD_write_lock(rand_meth_lock))
return 0;
# ifndef OPENSSL_NO_ENGINE
ENGINE_finish(funct_ref);
funct_ref = e;
# endif
default_RAND_meth = meth;
CRYPTO_THREAD_unlock(rand_meth_lock);
return 1;
}
int RAND_set_rand_method(const RAND_METHOD *meth)
{
return rand_set_rand_method_internal(meth, NULL);
}
const RAND_METHOD *RAND_get_rand_method(void)
{
const RAND_METHOD *tmp_meth = NULL;
if (!RUN_ONCE(&rand_init, do_rand_init))
return NULL;
if (!CRYPTO_THREAD_write_lock(rand_meth_lock))
return NULL;
if (default_RAND_meth == NULL) {
# ifndef OPENSSL_NO_ENGINE
ENGINE *e;
/* If we have an engine that can do RAND, use it. */
if ((e = ENGINE_get_default_RAND()) != NULL
&& (tmp_meth = ENGINE_get_RAND(e)) != NULL) {
funct_ref = e;
default_RAND_meth = tmp_meth;
} else {
ENGINE_finish(e);
default_RAND_meth = &ossl_rand_meth;
}
# else
default_RAND_meth = &ossl_rand_meth;
# endif
}
tmp_meth = default_RAND_meth;
CRYPTO_THREAD_unlock(rand_meth_lock);
return tmp_meth;
}
# if !defined(OPENSSL_NO_ENGINE)
int RAND_set_rand_engine(ENGINE *engine)
{
const RAND_METHOD *tmp_meth = NULL;
if (!RUN_ONCE(&rand_init, do_rand_init))
return 0;
if (engine != NULL) {
if (!ENGINE_init(engine))
return 0;
tmp_meth = ENGINE_get_RAND(engine);
if (tmp_meth == NULL) {
ENGINE_finish(engine);
return 0;
}
}
if (!CRYPTO_THREAD_write_lock(rand_engine_lock)) {
ENGINE_finish(engine);
return 0;
}
/* This function releases any prior ENGINE so call it first */
rand_set_rand_method_internal(tmp_meth, engine);
CRYPTO_THREAD_unlock(rand_engine_lock);
return 1;
}
# endif
# endif /* OPENSSL_NO_DEPRECATED_3_0 */
void RAND_seed(const void *buf, int num)
{
EVP_RAND_CTX *drbg;
# ifndef OPENSSL_NO_DEPRECATED_3_0
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth != NULL && meth->seed != NULL) {
meth->seed(buf, num);
return;
}
# endif
drbg = RAND_get0_primary(NULL);
if (drbg != NULL && num > 0)
EVP_RAND_reseed(drbg, 0, NULL, 0, buf, num);
}
void RAND_add(const void *buf, int num, double randomness)
{
EVP_RAND_CTX *drbg;
# ifndef OPENSSL_NO_DEPRECATED_3_0
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth != NULL && meth->add != NULL) {
meth->add(buf, num, randomness);
return;
}
# endif
drbg = RAND_get0_primary(NULL);
if (drbg != NULL && num > 0)
+# ifdef OPENSSL_RAND_SEED_NONE
+ /* Without an entropy source, we have to rely on the user */
+ EVP_RAND_reseed(drbg, 0, buf, num, NULL, 0);
+# else
+ /* With an entropy source, we downgrade this to additional input */
EVP_RAND_reseed(drbg, 0, NULL, 0, buf, num);
+# endif
}
# if !defined(OPENSSL_NO_DEPRECATED_1_1_0)
int RAND_pseudo_bytes(unsigned char *buf, int num)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth != NULL && meth->pseudorand != NULL)
return meth->pseudorand(buf, num);
ERR_raise(ERR_LIB_RAND, RAND_R_FUNC_NOT_IMPLEMENTED);
return -1;
}
# endif
int RAND_status(void)
{
EVP_RAND_CTX *rand;
# ifndef OPENSSL_NO_DEPRECATED_3_0
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth != NULL && meth != RAND_OpenSSL())
return meth->status != NULL ? meth->status() : 0;
# endif
if ((rand = RAND_get0_primary(NULL)) == NULL)
return 0;
return EVP_RAND_get_state(rand) == EVP_RAND_STATE_READY;
}
# else /* !FIPS_MODULE */
# ifndef OPENSSL_NO_DEPRECATED_3_0
const RAND_METHOD *RAND_get_rand_method(void)
{
return NULL;
}
# endif
#endif /* !FIPS_MODULE */
/*
* This function is not part of RAND_METHOD, so if we're not using
* the default method, then just call RAND_bytes(). Otherwise make
* sure we're instantiated and use the private DRBG.
*/
int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
unsigned int strength)
{
EVP_RAND_CTX *rand;
#if !defined(OPENSSL_NO_DEPRECATED_3_0) && !defined(FIPS_MODULE)
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth != NULL && meth != RAND_OpenSSL()) {
if (meth->bytes != NULL)
return meth->bytes(buf, num);
ERR_raise(ERR_LIB_RAND, RAND_R_FUNC_NOT_IMPLEMENTED);
return -1;
}
#endif
rand = RAND_get0_private(ctx);
if (rand != NULL)
return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0);
return 0;
}
int RAND_priv_bytes(unsigned char *buf, int num)
{
if (num < 0)
return 0;
return RAND_priv_bytes_ex(NULL, buf, (size_t)num, 0);
}
int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num,
unsigned int strength)
{
EVP_RAND_CTX *rand;
#if !defined(OPENSSL_NO_DEPRECATED_3_0) && !defined(FIPS_MODULE)
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth != NULL && meth != RAND_OpenSSL()) {
if (meth->bytes != NULL)
return meth->bytes(buf, num);
ERR_raise(ERR_LIB_RAND, RAND_R_FUNC_NOT_IMPLEMENTED);
return -1;
}
#endif
rand = RAND_get0_public(ctx);
if (rand != NULL)
return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0);
return 0;
}
int RAND_bytes(unsigned char *buf, int num)
{
if (num < 0)
return 0;
return RAND_bytes_ex(NULL, buf, (size_t)num, 0);
}
typedef struct rand_global_st {
/*
* The three shared DRBG instances
*
* There are three shared DRBG instances: <primary>, <public>, and
* <private>. The <public> and <private> DRBGs are secondary ones.
* These are used for non-secret (e.g. nonces) and secret
* (e.g. private keys) data respectively.
*/
CRYPTO_RWLOCK *lock;
EVP_RAND_CTX *seed;
/*
* The <primary> DRBG
*
* Not used directly by the application, only for reseeding the two other
* DRBGs. It reseeds itself by pulling either randomness from os entropy
* sources or by consuming randomness which was added by RAND_add().
*
* The <primary> DRBG is a global instance which is accessed concurrently by
* all threads. The necessary locking is managed automatically by its child
* DRBG instances during reseeding.
*/
EVP_RAND_CTX *primary;
/*
* The <public> DRBG
*
* Used by default for generating random bytes using RAND_bytes().
*
* The <public> secondary DRBG is thread-local, i.e., there is one instance
* per thread.
*/
CRYPTO_THREAD_LOCAL public;
/*
* The <private> DRBG
*
* Used by default for generating private keys using RAND_priv_bytes()
*
* The <private> secondary DRBG is thread-local, i.e., there is one
* instance per thread.
*/
CRYPTO_THREAD_LOCAL private;
/* Which RNG is being used by default and it's configuration settings */
char *rng_name;
char *rng_cipher;
char *rng_digest;
char *rng_propq;
/* Allow the randomness source to be changed */
char *seed_name;
char *seed_propq;
} RAND_GLOBAL;
/*
* Initialize the OSSL_LIB_CTX global DRBGs on first use.
* Returns the allocated global data on success or NULL on failure.
*/
static void *rand_ossl_ctx_new(OSSL_LIB_CTX *libctx)
{
RAND_GLOBAL *dgbl = OPENSSL_zalloc(sizeof(*dgbl));
if (dgbl == NULL)
return NULL;
#ifndef FIPS_MODULE
/*
* We need to ensure that base libcrypto thread handling has been
* initialised.
*/
OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL);
#endif
dgbl->lock = CRYPTO_THREAD_lock_new();
if (dgbl->lock == NULL)
goto err1;
if (!CRYPTO_THREAD_init_local(&dgbl->private, NULL))
goto err1;
if (!CRYPTO_THREAD_init_local(&dgbl->public, NULL))
goto err2;
return dgbl;
err2:
CRYPTO_THREAD_cleanup_local(&dgbl->private);
err1:
CRYPTO_THREAD_lock_free(dgbl->lock);
OPENSSL_free(dgbl);
return NULL;
}
void ossl_rand_ctx_free(void *vdgbl)
{
RAND_GLOBAL *dgbl = vdgbl;
if (dgbl == NULL)
return;
CRYPTO_THREAD_lock_free(dgbl->lock);
CRYPTO_THREAD_cleanup_local(&dgbl->private);
CRYPTO_THREAD_cleanup_local(&dgbl->public);
EVP_RAND_CTX_free(dgbl->primary);
EVP_RAND_CTX_free(dgbl->seed);
OPENSSL_free(dgbl->rng_name);
OPENSSL_free(dgbl->rng_cipher);
OPENSSL_free(dgbl->rng_digest);
OPENSSL_free(dgbl->rng_propq);
OPENSSL_free(dgbl->seed_name);
OPENSSL_free(dgbl->seed_propq);
OPENSSL_free(dgbl);
}
static const OSSL_LIB_CTX_METHOD rand_drbg_ossl_ctx_method = {
OSSL_LIB_CTX_METHOD_PRIORITY_2,
rand_ossl_ctx_new,
ossl_rand_ctx_free,
};
static RAND_GLOBAL *rand_get_global(OSSL_LIB_CTX *libctx)
{
return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_INDEX,
&rand_drbg_ossl_ctx_method);
}
static void rand_delete_thread_state(void *arg)
{
OSSL_LIB_CTX *ctx = arg;
RAND_GLOBAL *dgbl = rand_get_global(ctx);
EVP_RAND_CTX *rand;
if (dgbl == NULL)
return;
rand = CRYPTO_THREAD_get_local(&dgbl->public);
CRYPTO_THREAD_set_local(&dgbl->public, NULL);
EVP_RAND_CTX_free(rand);
rand = CRYPTO_THREAD_get_local(&dgbl->private);
CRYPTO_THREAD_set_local(&dgbl->private, NULL);
EVP_RAND_CTX_free(rand);
}
#ifndef FIPS_MODULE
static EVP_RAND_CTX *rand_new_seed(OSSL_LIB_CTX *libctx)
{
EVP_RAND *rand;
RAND_GLOBAL *dgbl = rand_get_global(libctx);
EVP_RAND_CTX *ctx;
char *name;
if (dgbl == NULL)
return NULL;
name = dgbl->seed_name != NULL ? dgbl->seed_name : "SEED-SRC";
rand = EVP_RAND_fetch(libctx, name, dgbl->seed_propq);
if (rand == NULL) {
ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG);
return NULL;
}
ctx = EVP_RAND_CTX_new(rand, NULL);
EVP_RAND_free(rand);
if (ctx == NULL) {
ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_CREATE_DRBG);
return NULL;
}
if (!EVP_RAND_instantiate(ctx, 0, 0, NULL, 0, NULL)) {
ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_INSTANTIATING_DRBG);
EVP_RAND_CTX_free(ctx);
return NULL;
}
return ctx;
}
#endif
static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent,
unsigned int reseed_interval,
time_t reseed_time_interval)
{
EVP_RAND *rand;
RAND_GLOBAL *dgbl = rand_get_global(libctx);
EVP_RAND_CTX *ctx;
OSSL_PARAM params[7], *p = params;
char *name, *cipher;
if (dgbl == NULL)
return NULL;
name = dgbl->rng_name != NULL ? dgbl->rng_name : "CTR-DRBG";
rand = EVP_RAND_fetch(libctx, name, dgbl->rng_propq);
if (rand == NULL) {
ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG);
return NULL;
}
ctx = EVP_RAND_CTX_new(rand, parent);
EVP_RAND_free(rand);
if (ctx == NULL) {
ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_CREATE_DRBG);
return NULL;
}
/*
* Rather than trying to decode the DRBG settings, just pass them through
* and rely on the other end to ignore those it doesn't care about.
*/
cipher = dgbl->rng_cipher != NULL ? dgbl->rng_cipher : "AES-256-CTR";
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER,
cipher, 0);
if (dgbl->rng_digest != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST,
dgbl->rng_digest, 0);
if (dgbl->rng_propq != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_PROPERTIES,
dgbl->rng_propq, 0);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_MAC, "HMAC", 0);
*p++ = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS,
&reseed_interval);
*p++ = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL,
&reseed_time_interval);
*p = OSSL_PARAM_construct_end();
if (!EVP_RAND_instantiate(ctx, 0, 0, NULL, 0, params)) {
ERR_raise(ERR_LIB_RAND, RAND_R_ERROR_INSTANTIATING_DRBG);
EVP_RAND_CTX_free(ctx);
return NULL;
}
return ctx;
}
/*
* Get the primary random generator.
* Returns pointer to its EVP_RAND_CTX on success, NULL on failure.
*
*/
EVP_RAND_CTX *RAND_get0_primary(OSSL_LIB_CTX *ctx)
{
RAND_GLOBAL *dgbl = rand_get_global(ctx);
EVP_RAND_CTX *ret;
if (dgbl == NULL)
return NULL;
if (!CRYPTO_THREAD_read_lock(dgbl->lock))
return NULL;
ret = dgbl->primary;
CRYPTO_THREAD_unlock(dgbl->lock);
if (ret != NULL)
return ret;
if (!CRYPTO_THREAD_write_lock(dgbl->lock))
return NULL;
ret = dgbl->primary;
if (ret != NULL) {
CRYPTO_THREAD_unlock(dgbl->lock);
return ret;
}
#ifndef FIPS_MODULE
if (dgbl->seed == NULL) {
ERR_set_mark();
dgbl->seed = rand_new_seed(ctx);
ERR_pop_to_mark();
}
#endif
ret = dgbl->primary = rand_new_drbg(ctx, dgbl->seed,
PRIMARY_RESEED_INTERVAL,
PRIMARY_RESEED_TIME_INTERVAL);
/*
* The primary DRBG may be shared between multiple threads so we must
* enable locking.
*/
if (ret != NULL && !EVP_RAND_enable_locking(ret)) {
ERR_raise(ERR_LIB_EVP, EVP_R_UNABLE_TO_ENABLE_LOCKING);
EVP_RAND_CTX_free(ret);
ret = dgbl->primary = NULL;
}
CRYPTO_THREAD_unlock(dgbl->lock);
return ret;
}
/*
* Get the public random generator.
* Returns pointer to its EVP_RAND_CTX on success, NULL on failure.
*/
EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx)
{
RAND_GLOBAL *dgbl = rand_get_global(ctx);
EVP_RAND_CTX *rand, *primary;
if (dgbl == NULL)
return NULL;
rand = CRYPTO_THREAD_get_local(&dgbl->public);
if (rand == NULL) {
primary = RAND_get0_primary(ctx);
if (primary == NULL)
return NULL;
ctx = ossl_lib_ctx_get_concrete(ctx);
/*
* If the private is also NULL then this is the first time we've
* used this thread.
*/
if (CRYPTO_THREAD_get_local(&dgbl->private) == NULL
&& !ossl_init_thread_start(NULL, ctx, rand_delete_thread_state))
return NULL;
rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL,
SECONDARY_RESEED_TIME_INTERVAL);
CRYPTO_THREAD_set_local(&dgbl->public, rand);
}
return rand;
}
/*
* Get the private random generator.
* Returns pointer to its EVP_RAND_CTX on success, NULL on failure.
*/
EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx)
{
RAND_GLOBAL *dgbl = rand_get_global(ctx);
EVP_RAND_CTX *rand, *primary;
if (dgbl == NULL)
return NULL;
rand = CRYPTO_THREAD_get_local(&dgbl->private);
if (rand == NULL) {
primary = RAND_get0_primary(ctx);
if (primary == NULL)
return NULL;
ctx = ossl_lib_ctx_get_concrete(ctx);
/*
* If the public is also NULL then this is the first time we've
* used this thread.
*/
if (CRYPTO_THREAD_get_local(&dgbl->public) == NULL
&& !ossl_init_thread_start(NULL, ctx, rand_delete_thread_state))
return NULL;
rand = rand_new_drbg(ctx, primary, SECONDARY_RESEED_INTERVAL,
SECONDARY_RESEED_TIME_INTERVAL);
CRYPTO_THREAD_set_local(&dgbl->private, rand);
}
return rand;
}
#ifndef FIPS_MODULE
static int random_set_string(char **p, const char *s)
{
char *d = NULL;
if (s != NULL) {
d = OPENSSL_strdup(s);
if (d == NULL) {
ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;
}
}
OPENSSL_free(*p);
*p = d;
return 1;
}
/*
* Load the DRBG definitions from a configuration file.
*/
static int random_conf_init(CONF_IMODULE *md, const CONF *cnf)
{
STACK_OF(CONF_VALUE) *elist;
CONF_VALUE *cval;
RAND_GLOBAL *dgbl = rand_get_global(NCONF_get0_libctx((CONF *)cnf));
int i, r = 1;
OSSL_TRACE1(CONF, "Loading random module: section %s\n",
CONF_imodule_get_value(md));
/* Value is a section containing RANDOM configuration */
elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));
if (elist == NULL) {
ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_RANDOM_SECTION_ERROR);
return 0;
}
if (dgbl == NULL)
return 0;
for (i = 0; i < sk_CONF_VALUE_num(elist); i++) {
cval = sk_CONF_VALUE_value(elist, i);
if (OPENSSL_strcasecmp(cval->name, "random") == 0) {
if (!random_set_string(&dgbl->rng_name, cval->value))
return 0;
} else if (OPENSSL_strcasecmp(cval->name, "cipher") == 0) {
if (!random_set_string(&dgbl->rng_cipher, cval->value))
return 0;
} else if (OPENSSL_strcasecmp(cval->name, "digest") == 0) {
if (!random_set_string(&dgbl->rng_digest, cval->value))
return 0;
} else if (OPENSSL_strcasecmp(cval->name, "properties") == 0) {
if (!random_set_string(&dgbl->rng_propq, cval->value))
return 0;
} else if (OPENSSL_strcasecmp(cval->name, "seed") == 0) {
if (!random_set_string(&dgbl->seed_name, cval->value))
return 0;
} else if (OPENSSL_strcasecmp(cval->name, "seed_properties") == 0) {
if (!random_set_string(&dgbl->seed_propq, cval->value))
return 0;
} else {
ERR_raise_data(ERR_LIB_CRYPTO,
CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION,
"name=%s, value=%s", cval->name, cval->value);
r = 0;
}
}
return r;
}
static void random_conf_deinit(CONF_IMODULE *md)
{
OSSL_TRACE(CONF, "Cleaned up random\n");
}
void ossl_random_add_conf_module(void)
{
OSSL_TRACE(CONF, "Adding config module 'random'\n");
CONF_module_add("random", random_conf_init, random_conf_deinit);
}
int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq,
const char *cipher, const char *digest)
{
RAND_GLOBAL *dgbl = rand_get_global(ctx);
if (dgbl == NULL)
return 0;
if (dgbl->primary != NULL) {
ERR_raise(ERR_LIB_CRYPTO, RAND_R_ALREADY_INSTANTIATED);
return 0;
}
return random_set_string(&dgbl->rng_name, drbg)
&& random_set_string(&dgbl->rng_propq, propq)
&& random_set_string(&dgbl->rng_cipher, cipher)
&& random_set_string(&dgbl->rng_digest, digest);
}
int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed,
const char *propq)
{
RAND_GLOBAL *dgbl = rand_get_global(ctx);
if (dgbl == NULL)
return 0;
if (dgbl->primary != NULL) {
ERR_raise(ERR_LIB_CRYPTO, RAND_R_ALREADY_INSTANTIATED);
return 0;
}
return random_set_string(&dgbl->seed_name, seed)
&& random_set_string(&dgbl->seed_propq, propq);
}
#endif
diff --git a/crypto/rsa/rsa_chk.c b/crypto/rsa/rsa_chk.c
index cccc2d5bac2a..c2549188f556 100644
--- a/crypto/rsa/rsa_chk.c
+++ b/crypto/rsa/rsa_chk.c
@@ -1,266 +1,270 @@
/*
- * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-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
*/
/*
* RSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <openssl/bn.h>
#include <openssl/err.h>
#include "crypto/rsa.h"
#include "rsa_local.h"
#ifndef FIPS_MODULE
static int rsa_validate_keypair_multiprime(const RSA *key, BN_GENCB *cb)
{
BIGNUM *i, *j, *k, *l, *m;
BN_CTX *ctx;
int ret = 1, ex_primes = 0, idx;
RSA_PRIME_INFO *pinfo;
if (key->p == NULL || key->q == NULL || key->n == NULL
|| key->e == NULL || key->d == NULL) {
ERR_raise(ERR_LIB_RSA, RSA_R_VALUE_MISSING);
return 0;
}
/* multi-prime? */
if (key->version == RSA_ASN1_VERSION_MULTI) {
ex_primes = sk_RSA_PRIME_INFO_num(key->prime_infos);
if (ex_primes <= 0
|| (ex_primes + 2) > ossl_rsa_multip_cap(BN_num_bits(key->n))) {
ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MULTI_PRIME_KEY);
return 0;
}
}
i = BN_new();
j = BN_new();
k = BN_new();
l = BN_new();
m = BN_new();
ctx = BN_CTX_new_ex(key->libctx);
if (i == NULL || j == NULL || k == NULL || l == NULL
|| m == NULL || ctx == NULL) {
ret = -1;
ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
if (BN_is_one(key->e)) {
ret = 0;
ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
}
if (!BN_is_odd(key->e)) {
ret = 0;
ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
}
/* p prime? */
if (BN_check_prime(key->p, ctx, cb) != 1) {
ret = 0;
ERR_raise(ERR_LIB_RSA, RSA_R_P_NOT_PRIME);
}
/* q prime? */
if (BN_check_prime(key->q, ctx, cb) != 1) {
ret = 0;
ERR_raise(ERR_LIB_RSA, RSA_R_Q_NOT_PRIME);
}
/* r_i prime? */
for (idx = 0; idx < ex_primes; idx++) {
pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
if (BN_check_prime(pinfo->r, ctx, cb) != 1) {
ret = 0;
ERR_raise(ERR_LIB_RSA, RSA_R_MP_R_NOT_PRIME);
}
}
/* n = p*q * r_3...r_i? */
if (!BN_mul(i, key->p, key->q, ctx)) {
ret = -1;
goto err;
}
for (idx = 0; idx < ex_primes; idx++) {
pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
if (!BN_mul(i, i, pinfo->r, ctx)) {
ret = -1;
goto err;
}
}
if (BN_cmp(i, key->n) != 0) {
ret = 0;
if (ex_primes)
ERR_raise(ERR_LIB_RSA, RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES);
else
ERR_raise(ERR_LIB_RSA, RSA_R_N_DOES_NOT_EQUAL_P_Q);
}
/* d*e = 1 mod \lambda(n)? */
if (!BN_sub(i, key->p, BN_value_one())) {
ret = -1;
goto err;
}
if (!BN_sub(j, key->q, BN_value_one())) {
ret = -1;
goto err;
}
/* now compute k = \lambda(n) = LCM(i, j, r_3 - 1...) */
if (!BN_mul(l, i, j, ctx)) {
ret = -1;
goto err;
}
if (!BN_gcd(m, i, j, ctx)) {
ret = -1;
goto err;
}
+ if (!BN_div(m, NULL, l, m, ctx)) { /* remainder is 0 */
+ ret = -1;
+ goto err;
+ }
for (idx = 0; idx < ex_primes; idx++) {
pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
if (!BN_sub(k, pinfo->r, BN_value_one())) {
ret = -1;
goto err;
}
- if (!BN_mul(l, l, k, ctx)) {
+ if (!BN_mul(l, m, k, ctx)) {
ret = -1;
goto err;
}
if (!BN_gcd(m, m, k, ctx)) {
ret = -1;
goto err;
}
+ if (!BN_div(m, NULL, l, m, ctx)) { /* remainder is 0 */
+ ret = -1;
+ goto err;
+ }
}
- if (!BN_div(k, NULL, l, m, ctx)) { /* remainder is 0 */
- ret = -1;
- goto err;
- }
- if (!BN_mod_mul(i, key->d, key->e, k, ctx)) {
+ if (!BN_mod_mul(i, key->d, key->e, m, ctx)) {
ret = -1;
goto err;
}
if (!BN_is_one(i)) {
ret = 0;
ERR_raise(ERR_LIB_RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1);
}
if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) {
/* dmp1 = d mod (p-1)? */
if (!BN_sub(i, key->p, BN_value_one())) {
ret = -1;
goto err;
}
if (!BN_mod(j, key->d, i, ctx)) {
ret = -1;
goto err;
}
if (BN_cmp(j, key->dmp1) != 0) {
ret = 0;
ERR_raise(ERR_LIB_RSA, RSA_R_DMP1_NOT_CONGRUENT_TO_D);
}
/* dmq1 = d mod (q-1)? */
if (!BN_sub(i, key->q, BN_value_one())) {
ret = -1;
goto err;
}
if (!BN_mod(j, key->d, i, ctx)) {
ret = -1;
goto err;
}
if (BN_cmp(j, key->dmq1) != 0) {
ret = 0;
ERR_raise(ERR_LIB_RSA, RSA_R_DMQ1_NOT_CONGRUENT_TO_D);
}
/* iqmp = q^-1 mod p? */
if (!BN_mod_inverse(i, key->q, key->p, ctx)) {
ret = -1;
goto err;
}
if (BN_cmp(i, key->iqmp) != 0) {
ret = 0;
ERR_raise(ERR_LIB_RSA, RSA_R_IQMP_NOT_INVERSE_OF_Q);
}
}
for (idx = 0; idx < ex_primes; idx++) {
pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
/* d_i = d mod (r_i - 1)? */
if (!BN_sub(i, pinfo->r, BN_value_one())) {
ret = -1;
goto err;
}
if (!BN_mod(j, key->d, i, ctx)) {
ret = -1;
goto err;
}
if (BN_cmp(j, pinfo->d) != 0) {
ret = 0;
ERR_raise(ERR_LIB_RSA, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D);
}
/* t_i = R_i ^ -1 mod r_i ? */
if (!BN_mod_inverse(i, pinfo->pp, pinfo->r, ctx)) {
ret = -1;
goto err;
}
if (BN_cmp(i, pinfo->t) != 0) {
ret = 0;
ERR_raise(ERR_LIB_RSA, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R);
}
}
err:
BN_free(i);
BN_free(j);
BN_free(k);
BN_free(l);
BN_free(m);
BN_CTX_free(ctx);
return ret;
}
#endif /* FIPS_MODULE */
int ossl_rsa_validate_public(const RSA *key)
{
return ossl_rsa_sp800_56b_check_public(key);
}
int ossl_rsa_validate_private(const RSA *key)
{
return ossl_rsa_sp800_56b_check_private(key);
}
int ossl_rsa_validate_pairwise(const RSA *key)
{
#ifdef FIPS_MODULE
return ossl_rsa_sp800_56b_check_keypair(key, NULL, -1, RSA_bits(key));
#else
return rsa_validate_keypair_multiprime(key, NULL) > 0;
#endif
}
int RSA_check_key(const RSA *key)
{
return RSA_check_key_ex(key, NULL);
}
int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
{
#ifdef FIPS_MODULE
return ossl_rsa_validate_public(key)
&& ossl_rsa_validate_private(key)
&& ossl_rsa_validate_pairwise(key);
#else
return rsa_validate_keypair_multiprime(key, cb);
#endif /* FIPS_MODULE */
}
diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c
index 96fed3ca597c..0fc642e777fd 100644
--- a/crypto/rsa/rsa_ossl.c
+++ b/crypto/rsa/rsa_ossl.c
@@ -1,1008 +1,1000 @@
/*
* 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
*/
/*
* RSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include "internal/cryptlib.h"
#include "crypto/bn.h"
#include "rsa_local.h"
#include "internal/constant_time.h"
static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *i, RSA *rsa,
BN_CTX *ctx);
static int rsa_ossl_init(RSA *rsa);
static int rsa_ossl_finish(RSA *rsa);
static RSA_METHOD rsa_pkcs1_ossl_meth = {
"OpenSSL PKCS#1 RSA",
rsa_ossl_public_encrypt,
rsa_ossl_public_decrypt, /* signature verification */
rsa_ossl_private_encrypt, /* signing */
rsa_ossl_private_decrypt,
rsa_ossl_mod_exp,
BN_mod_exp_mont, /* XXX probably we should not use Montgomery
* if e == 3 */
rsa_ossl_init,
rsa_ossl_finish,
RSA_FLAG_FIPS_METHOD, /* flags */
NULL,
0, /* rsa_sign */
0, /* rsa_verify */
NULL, /* rsa_keygen */
NULL /* rsa_multi_prime_keygen */
};
static const RSA_METHOD *default_RSA_meth = &rsa_pkcs1_ossl_meth;
void RSA_set_default_method(const RSA_METHOD *meth)
{
default_RSA_meth = meth;
}
const RSA_METHOD *RSA_get_default_method(void)
{
return default_RSA_meth;
}
const RSA_METHOD *RSA_PKCS1_OpenSSL(void)
{
return &rsa_pkcs1_ossl_meth;
}
const RSA_METHOD *RSA_null_method(void)
{
return NULL;
}
static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
BIGNUM *f, *ret;
int i, num = 0, r = -1;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
ERR_raise(ERR_LIB_RSA, RSA_R_MODULUS_TOO_LARGE);
return -1;
}
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
return -1;
}
/* for large moduli, enforce exponent limit */
if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) {
if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
return -1;
}
}
if ((ctx = BN_CTX_new_ex(rsa->libctx)) == NULL)
goto err;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
ret = BN_CTX_get(ctx);
num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if (ret == NULL || buf == NULL) {
ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
switch (padding) {
case RSA_PKCS1_PADDING:
i = ossl_rsa_padding_add_PKCS1_type_2_ex(rsa->libctx, buf, num,
from, flen);
break;
case RSA_PKCS1_OAEP_PADDING:
i = ossl_rsa_padding_add_PKCS1_OAEP_mgf1_ex(rsa->libctx, buf, num,
from, flen, NULL, 0,
NULL, NULL);
break;
case RSA_NO_PADDING:
i = RSA_padding_add_none(buf, num, from, flen);
break;
default:
ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (i <= 0)
goto err;
if (BN_bin2bn(buf, num, f) == NULL)
goto err;
if (BN_ucmp(f, rsa->n) >= 0) {
/* usually the padding functions would catch this */
ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
rsa->n, ctx))
goto err;
if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx,
rsa->_method_mod_n))
goto err;
/*
* BN_bn2binpad puts in leading 0 bytes if the number is less than
* the length of the modulus.
*/
r = BN_bn2binpad(ret, to, num);
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
}
static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
{
BN_BLINDING *ret;
if (!CRYPTO_THREAD_write_lock(rsa->lock))
return NULL;
if (rsa->blinding == NULL) {
rsa->blinding = RSA_setup_blinding(rsa, ctx);
}
ret = rsa->blinding;
if (ret == NULL)
goto err;
if (BN_BLINDING_is_current_thread(ret)) {
/* rsa->blinding is ours! */
*local = 1;
} else {
/* resort to rsa->mt_blinding instead */
/*
* instructs rsa_blinding_convert(), rsa_blinding_invert() that the
* BN_BLINDING is shared, meaning that accesses require locks, and
* that the blinding factor must be stored outside the BN_BLINDING
*/
*local = 0;
if (rsa->mt_blinding == NULL) {
rsa->mt_blinding = RSA_setup_blinding(rsa, ctx);
}
ret = rsa->mt_blinding;
}
err:
CRYPTO_THREAD_unlock(rsa->lock);
return ret;
}
static int rsa_blinding_convert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
BN_CTX *ctx)
{
if (unblind == NULL) {
/*
* Local blinding: store the unblinding factor in BN_BLINDING.
*/
return BN_BLINDING_convert_ex(f, NULL, b, ctx);
} else {
/*
* Shared blinding: store the unblinding factor outside BN_BLINDING.
*/
int ret;
if (!BN_BLINDING_lock(b))
return 0;
ret = BN_BLINDING_convert_ex(f, unblind, b, ctx);
BN_BLINDING_unlock(b);
return ret;
}
}
static int rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
BN_CTX *ctx)
{
/*
* For local blinding, unblind is set to NULL, and BN_BLINDING_invert_ex
* will use the unblinding factor stored in BN_BLINDING. If BN_BLINDING
* is shared between threads, unblind must be non-null:
* BN_BLINDING_invert_ex will then use the local unblinding factor, and
* will only read the modulus from BN_BLINDING. In both cases it's safe
* to access the blinding without a lock.
*/
+ BN_set_flags(f, BN_FLG_CONSTTIME);
return BN_BLINDING_invert_ex(f, unblind, b, ctx);
}
/* signing */
static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
BIGNUM *f, *ret, *res;
int i, num = 0, r = -1;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
int local_blinding = 0;
/*
* Used only if the blinding structure is shared. A non-NULL unblind
* instructs rsa_blinding_convert() and rsa_blinding_invert() to store
* the unblinding factor outside the blinding structure.
*/
BIGNUM *unblind = NULL;
BN_BLINDING *blinding = NULL;
if ((ctx = BN_CTX_new_ex(rsa->libctx)) == NULL)
goto err;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
ret = BN_CTX_get(ctx);
num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if (ret == NULL || buf == NULL) {
ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
switch (padding) {
case RSA_PKCS1_PADDING:
i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen);
break;
case RSA_X931_PADDING:
i = RSA_padding_add_X931(buf, num, from, flen);
break;
case RSA_NO_PADDING:
i = RSA_padding_add_none(buf, num, from, flen);
break;
default:
ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (i <= 0)
goto err;
if (BN_bin2bn(buf, num, f) == NULL)
goto err;
if (BN_ucmp(f, rsa->n) >= 0) {
/* usually the padding functions would catch this */
ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
rsa->n, ctx))
goto err;
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
if (blinding == NULL) {
ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (blinding != NULL) {
if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!rsa_blinding_convert(blinding, f, unblind, ctx))
goto err;
}
if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
(rsa->version == RSA_ASN1_VERSION_MULTI) ||
((rsa->p != NULL) &&
(rsa->q != NULL) &&
(rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) {
if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx))
goto err;
} else {
BIGNUM *d = BN_new();
if (d == NULL) {
ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
if (rsa->d == NULL) {
ERR_raise(ERR_LIB_RSA, RSA_R_MISSING_PRIVATE_KEY);
BN_free(d);
goto err;
}
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx,
rsa->_method_mod_n)) {
BN_free(d);
goto err;
}
/* We MUST free d before any further use of rsa->d */
BN_free(d);
}
if (blinding)
if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
goto err;
if (padding == RSA_X931_PADDING) {
if (!BN_sub(f, rsa->n, ret))
goto err;
if (BN_cmp(ret, f) > 0)
res = f;
else
res = ret;
} else {
res = ret;
}
/*
* BN_bn2binpad puts in leading 0 bytes if the number is less than
* the length of the modulus.
*/
r = BN_bn2binpad(res, to, num);
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
}
static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
BIGNUM *f, *ret;
int j, num = 0, r = -1;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
int local_blinding = 0;
/*
* Used only if the blinding structure is shared. A non-NULL unblind
* instructs rsa_blinding_convert() and rsa_blinding_invert() to store
* the unblinding factor outside the blinding structure.
*/
BIGNUM *unblind = NULL;
BN_BLINDING *blinding = NULL;
if ((ctx = BN_CTX_new_ex(rsa->libctx)) == NULL)
goto err;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
ret = BN_CTX_get(ctx);
num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if (ret == NULL || buf == NULL) {
ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
/*
* This check was for equality but PGP does evil things and chops off the
* top '0' bytes
*/
if (flen > num) {
ERR_raise(ERR_LIB_RSA, RSA_R_DATA_GREATER_THAN_MOD_LEN);
goto err;
}
/* make data into a big number */
if (BN_bin2bn(from, (int)flen, f) == NULL)
goto err;
if (BN_ucmp(f, rsa->n) >= 0) {
ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
+ if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
+ if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
+ rsa->n, ctx))
+ goto err;
+
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
if (blinding == NULL) {
ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (blinding != NULL) {
if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!rsa_blinding_convert(blinding, f, unblind, ctx))
goto err;
}
/* do the decrypt */
if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
(rsa->version == RSA_ASN1_VERSION_MULTI) ||
((rsa->p != NULL) &&
(rsa->q != NULL) &&
(rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) {
if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx))
goto err;
} else {
BIGNUM *d = BN_new();
if (d == NULL) {
ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
if (rsa->d == NULL) {
ERR_raise(ERR_LIB_RSA, RSA_R_MISSING_PRIVATE_KEY);
BN_free(d);
goto err;
}
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
-
- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
- if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
- rsa->n, ctx)) {
- BN_free(d);
- goto err;
- }
if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx,
rsa->_method_mod_n)) {
BN_free(d);
goto err;
}
/* We MUST free d before any further use of rsa->d */
BN_free(d);
}
- if (blinding) {
- /*
- * ossl_bn_rsa_do_unblind() combines blinding inversion and
- * 0-padded BN BE serialization
- */
- j = ossl_bn_rsa_do_unblind(ret, blinding, unblind, rsa->n, ctx,
- buf, num);
- if (j == 0)
- goto err;
- } else {
- j = BN_bn2binpad(ret, buf, num);
- if (j < 0)
+ if (blinding)
+ if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
goto err;
- }
+
+ j = BN_bn2binpad(ret, buf, num);
+ if (j < 0)
+ goto err;
switch (padding) {
case RSA_PKCS1_PADDING:
r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num);
break;
case RSA_PKCS1_OAEP_PADDING:
r = RSA_padding_check_PKCS1_OAEP(to, num, buf, j, num, NULL, 0);
break;
case RSA_NO_PADDING:
memcpy(to, buf, (r = j));
break;
default:
ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
#ifndef FIPS_MODULE
/*
* This trick doesn't work in the FIPS provider because libcrypto manages
* the error stack. Instead we opt not to put an error on the stack at all
* in case of padding failure in the FIPS provider.
*/
ERR_raise(ERR_LIB_RSA, RSA_R_PADDING_CHECK_FAILED);
err_clear_last_constant_time(1 & ~constant_time_msb(r));
#endif
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
}
/* signature verification */
static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
BIGNUM *f, *ret;
int i, num = 0, r = -1;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
ERR_raise(ERR_LIB_RSA, RSA_R_MODULUS_TOO_LARGE);
return -1;
}
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
return -1;
}
/* for large moduli, enforce exponent limit */
if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) {
if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE);
return -1;
}
}
if ((ctx = BN_CTX_new_ex(rsa->libctx)) == NULL)
goto err;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
ret = BN_CTX_get(ctx);
num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if (ret == NULL || buf == NULL) {
ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
/*
* This check was for equality but PGP does evil things and chops off the
* top '0' bytes
*/
if (flen > num) {
ERR_raise(ERR_LIB_RSA, RSA_R_DATA_GREATER_THAN_MOD_LEN);
goto err;
}
if (BN_bin2bn(from, flen, f) == NULL)
goto err;
if (BN_ucmp(f, rsa->n) >= 0) {
ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
rsa->n, ctx))
goto err;
if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx,
rsa->_method_mod_n))
goto err;
if ((padding == RSA_X931_PADDING) && ((bn_get_words(ret)[0] & 0xf) != 12))
if (!BN_sub(ret, rsa->n, ret))
goto err;
i = BN_bn2binpad(ret, buf, num);
if (i < 0)
goto err;
switch (padding) {
case RSA_PKCS1_PADDING:
r = RSA_padding_check_PKCS1_type_1(to, num, buf, i, num);
break;
case RSA_X931_PADDING:
r = RSA_padding_check_X931(to, num, buf, i, num);
break;
case RSA_NO_PADDING:
memcpy(to, buf, (r = i));
break;
default:
ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (r < 0)
ERR_raise(ERR_LIB_RSA, RSA_R_PADDING_CHECK_FAILED);
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
}
static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
{
BIGNUM *r1, *m1, *vrfy;
int ret = 0, smooth = 0;
#ifndef FIPS_MODULE
BIGNUM *r2, *m[RSA_MAX_PRIME_NUM - 2];
int i, ex_primes = 0;
RSA_PRIME_INFO *pinfo;
#endif
BN_CTX_start(ctx);
r1 = BN_CTX_get(ctx);
#ifndef FIPS_MODULE
r2 = BN_CTX_get(ctx);
#endif
m1 = BN_CTX_get(ctx);
vrfy = BN_CTX_get(ctx);
if (vrfy == NULL)
goto err;
#ifndef FIPS_MODULE
if (rsa->version == RSA_ASN1_VERSION_MULTI
&& ((ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) <= 0
|| ex_primes > RSA_MAX_PRIME_NUM - 2))
goto err;
#endif
if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
BIGNUM *factor = BN_new();
if (factor == NULL)
goto err;
/*
* Make sure BN_mod_inverse in Montgomery initialization uses the
* BN_FLG_CONSTTIME flag
*/
if (!(BN_with_flags(factor, rsa->p, BN_FLG_CONSTTIME),
BN_MONT_CTX_set_locked(&rsa->_method_mod_p, rsa->lock,
factor, ctx))
|| !(BN_with_flags(factor, rsa->q, BN_FLG_CONSTTIME),
BN_MONT_CTX_set_locked(&rsa->_method_mod_q, rsa->lock,
factor, ctx))) {
BN_free(factor);
goto err;
}
#ifndef FIPS_MODULE
for (i = 0; i < ex_primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
BN_with_flags(factor, pinfo->r, BN_FLG_CONSTTIME);
if (!BN_MONT_CTX_set_locked(&pinfo->m, rsa->lock, factor, ctx)) {
BN_free(factor);
goto err;
}
}
#endif
/*
* We MUST free |factor| before any further use of the prime factors
*/
BN_free(factor);
smooth = (rsa->meth->bn_mod_exp == BN_mod_exp_mont)
#ifndef FIPS_MODULE
&& (ex_primes == 0)
#endif
&& (BN_num_bits(rsa->q) == BN_num_bits(rsa->p));
}
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
rsa->n, ctx))
goto err;
if (smooth) {
/*
* Conversion from Montgomery domain, a.k.a. Montgomery reduction,
* accepts values in [0-m*2^w) range. w is m's bit width rounded up
* to limb width. So that at the very least if |I| is fully reduced,
* i.e. less than p*q, we can count on from-to round to perform
* below modulo operations on |I|. Unlike BN_mod it's constant time.
*/
if (/* m1 = I moq q */
!bn_from_mont_fixed_top(m1, I, rsa->_method_mod_q, ctx)
|| !bn_to_mont_fixed_top(m1, m1, rsa->_method_mod_q, ctx)
/* r1 = I mod p */
|| !bn_from_mont_fixed_top(r1, I, rsa->_method_mod_p, ctx)
|| !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx)
/*
* Use parallel exponentiations optimization if possible,
* otherwise fallback to two sequential exponentiations:
* m1 = m1^dmq1 mod q
* r1 = r1^dmp1 mod p
*/
|| !BN_mod_exp_mont_consttime_x2(m1, m1, rsa->dmq1, rsa->q,
rsa->_method_mod_q,
r1, r1, rsa->dmp1, rsa->p,
rsa->_method_mod_p,
ctx)
/* r1 = (r1 - m1) mod p */
/*
* bn_mod_sub_fixed_top is not regular modular subtraction,
* it can tolerate subtrahend to be larger than modulus, but
* not bit-wise wider. This makes up for uncommon q>p case,
* when |m1| can be larger than |rsa->p|.
*/
|| !bn_mod_sub_fixed_top(r1, r1, m1, rsa->p)
/* r1 = r1 * iqmp mod p */
|| !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx)
|| !bn_mul_mont_fixed_top(r1, r1, rsa->iqmp, rsa->_method_mod_p,
ctx)
/* r0 = r1 * q + m1 */
|| !bn_mul_fixed_top(r0, r1, rsa->q, ctx)
|| !bn_mod_add_fixed_top(r0, r0, m1, rsa->n))
goto err;
goto tail;
}
/* compute I mod q */
{
BIGNUM *c = BN_new();
if (c == NULL)
goto err;
BN_with_flags(c, I, BN_FLG_CONSTTIME);
if (!BN_mod(r1, c, rsa->q, ctx)) {
BN_free(c);
goto err;
}
{
BIGNUM *dmq1 = BN_new();
if (dmq1 == NULL) {
BN_free(c);
goto err;
}
BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
/* compute r1^dmq1 mod q */
if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx,
rsa->_method_mod_q)) {
BN_free(c);
BN_free(dmq1);
goto err;
}
/* We MUST free dmq1 before any further use of rsa->dmq1 */
BN_free(dmq1);
}
/* compute I mod p */
if (!BN_mod(r1, c, rsa->p, ctx)) {
BN_free(c);
goto err;
}
/* We MUST free c before any further use of I */
BN_free(c);
}
{
BIGNUM *dmp1 = BN_new();
if (dmp1 == NULL)
goto err;
BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
/* compute r1^dmp1 mod p */
if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx,
rsa->_method_mod_p)) {
BN_free(dmp1);
goto err;
}
/* We MUST free dmp1 before any further use of rsa->dmp1 */
BN_free(dmp1);
}
#ifndef FIPS_MODULE
if (ex_primes > 0) {
BIGNUM *di = BN_new(), *cc = BN_new();
if (cc == NULL || di == NULL) {
BN_free(cc);
BN_free(di);
goto err;
}
for (i = 0; i < ex_primes; i++) {
/* prepare m_i */
if ((m[i] = BN_CTX_get(ctx)) == NULL) {
BN_free(cc);
BN_free(di);
goto err;
}
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
/* prepare c and d_i */
BN_with_flags(cc, I, BN_FLG_CONSTTIME);
BN_with_flags(di, pinfo->d, BN_FLG_CONSTTIME);
if (!BN_mod(r1, cc, pinfo->r, ctx)) {
BN_free(cc);
BN_free(di);
goto err;
}
/* compute r1 ^ d_i mod r_i */
if (!rsa->meth->bn_mod_exp(m[i], r1, di, pinfo->r, ctx, pinfo->m)) {
BN_free(cc);
BN_free(di);
goto err;
}
}
BN_free(cc);
BN_free(di);
}
#endif
if (!BN_sub(r0, r0, m1))
goto err;
/*
* This will help stop the size of r0 increasing, which does affect the
* multiply if it optimised for a power of 2 size
*/
if (BN_is_negative(r0))
if (!BN_add(r0, r0, rsa->p))
goto err;
if (!BN_mul(r1, r0, rsa->iqmp, ctx))
goto err;
{
BIGNUM *pr1 = BN_new();
if (pr1 == NULL)
goto err;
BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);
if (!BN_mod(r0, pr1, rsa->p, ctx)) {
BN_free(pr1);
goto err;
}
/* We MUST free pr1 before any further use of r1 */
BN_free(pr1);
}
/*
* If p < q it is occasionally possible for the correction of adding 'p'
* if r0 is negative above to leave the result still negative. This can
* break the private key operations: the following second correction
* should *always* correct this rare occurrence. This will *never* happen
* with OpenSSL generated keys because they ensure p > q [steve]
*/
if (BN_is_negative(r0))
if (!BN_add(r0, r0, rsa->p))
goto err;
if (!BN_mul(r1, r0, rsa->q, ctx))
goto err;
if (!BN_add(r0, r1, m1))
goto err;
#ifndef FIPS_MODULE
/* add m_i to m in multi-prime case */
if (ex_primes > 0) {
BIGNUM *pr2 = BN_new();
if (pr2 == NULL)
goto err;
for (i = 0; i < ex_primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
if (!BN_sub(r1, m[i], r0)) {
BN_free(pr2);
goto err;
}
if (!BN_mul(r2, r1, pinfo->t, ctx)) {
BN_free(pr2);
goto err;
}
BN_with_flags(pr2, r2, BN_FLG_CONSTTIME);
if (!BN_mod(r1, pr2, pinfo->r, ctx)) {
BN_free(pr2);
goto err;
}
if (BN_is_negative(r1))
if (!BN_add(r1, r1, pinfo->r)) {
BN_free(pr2);
goto err;
}
if (!BN_mul(r1, r1, pinfo->pp, ctx)) {
BN_free(pr2);
goto err;
}
if (!BN_add(r0, r0, r1)) {
BN_free(pr2);
goto err;
}
}
BN_free(pr2);
}
#endif
tail:
if (rsa->e && rsa->n) {
if (rsa->meth->bn_mod_exp == BN_mod_exp_mont) {
if (!BN_mod_exp_mont(vrfy, r0, rsa->e, rsa->n, ctx,
rsa->_method_mod_n))
goto err;
} else {
bn_correct_top(r0);
if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx,
rsa->_method_mod_n))
goto err;
}
/*
* If 'I' was greater than (or equal to) rsa->n, the operation will
* be equivalent to using 'I mod n'. However, the result of the
* verify will *always* be less than 'n' so we don't check for
* absolute equality, just congruency.
*/
if (!BN_sub(vrfy, vrfy, I))
goto err;
if (BN_is_zero(vrfy)) {
bn_correct_top(r0);
ret = 1;
goto err; /* not actually error */
}
if (!BN_mod(vrfy, vrfy, rsa->n, ctx))
goto err;
if (BN_is_negative(vrfy))
if (!BN_add(vrfy, vrfy, rsa->n))
goto err;
if (!BN_is_zero(vrfy)) {
/*
* 'I' and 'vrfy' aren't congruent mod n. Don't leak
* miscalculated CRT output, just do a raw (slower) mod_exp and
* return that instead.
*/
BIGNUM *d = BN_new();
if (d == NULL)
goto err;
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx,
rsa->_method_mod_n)) {
BN_free(d);
goto err;
}
/* We MUST free d before any further use of rsa->d */
BN_free(d);
}
}
/*
* It's unfortunate that we have to bn_correct_top(r0). What hopefully
* saves the day is that correction is highly unlike, and private key
* operations are customarily performed on blinded message. Which means
* that attacker won't observe correlation with chosen plaintext.
* Secondly, remaining code would still handle it in same computational
* time and even conceal memory access pattern around corrected top.
*/
bn_correct_top(r0);
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
static int rsa_ossl_init(RSA *rsa)
{
rsa->flags |= RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE;
return 1;
}
static int rsa_ossl_finish(RSA *rsa)
{
#ifndef FIPS_MODULE
int i;
RSA_PRIME_INFO *pinfo;
for (i = 0; i < sk_RSA_PRIME_INFO_num(rsa->prime_infos); i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
BN_MONT_CTX_free(pinfo->m);
}
#endif
BN_MONT_CTX_free(rsa->_method_mod_n);
BN_MONT_CTX_free(rsa->_method_mod_p);
BN_MONT_CTX_free(rsa->_method_mod_q);
return 1;
}
diff --git a/crypto/rsa/rsa_sp800_56b_gen.c b/crypto/rsa/rsa_sp800_56b_gen.c
index df2240555bfd..f773d1e149de 100644
--- a/crypto/rsa/rsa_sp800_56b_gen.c
+++ b/crypto/rsa/rsa_sp800_56b_gen.c
@@ -1,440 +1,449 @@
/*
- * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018-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 <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/core.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include "crypto/bn.h"
#include "crypto/security_bits.h"
#include "rsa_local.h"
#define RSA_FIPS1864_MIN_KEYGEN_KEYSIZE 2048
#define RSA_FIPS1864_MIN_KEYGEN_STRENGTH 112
/*
* Generate probable primes 'p' & 'q'. See FIPS 186-4 Section B.3.6
* "Generation of Probable Primes with Conditions Based on Auxiliary Probable
* Primes".
*
* Params:
* rsa Object used to store primes p & q.
* test Object used for CAVS testing only.that contains..
* p1, p2 The returned auxiliary primes for p.
* If NULL they are not returned.
* Xpout An optionally returned random number used during generation of p.
* Xp An optional passed in value (that is random number used during
* generation of p).
* Xp1, Xp2 Optionally passed in randomly generated numbers from which
* auxiliary primes p1 & p2 are calculated. If NULL these values
* are generated internally.
* q1, q2 The returned auxiliary primes for q.
* If NULL they are not returned.
* Xqout An optionally returned random number used during generation of q.
* Xq An optional passed in value (that is random number used during
* generation of q).
* Xq1, Xq2 Optionally passed in randomly generated numbers from which
* auxiliary primes q1 & q2 are calculated. If NULL these values
* are generated internally.
* nbits The key size in bits (The size of the modulus n).
* e The public exponent.
* ctx A BN_CTX object.
* cb An optional BIGNUM callback.
* Returns: 1 if successful, or 0 otherwise.
* Notes:
* p1, p2, q1, q2, Xpout, Xqout are returned if they are not NULL.
* Xp, Xp1, Xp2, Xq, Xq1, Xq2 are optionally passed in.
* (Required for CAVS testing).
*/
int ossl_rsa_fips186_4_gen_prob_primes(RSA *rsa, RSA_ACVP_TEST *test,
int nbits, const BIGNUM *e, BN_CTX *ctx,
BN_GENCB *cb)
{
int ret = 0, ok;
/* Temp allocated BIGNUMS */
BIGNUM *Xpo = NULL, *Xqo = NULL, *tmp = NULL;
/* Intermediate BIGNUMS that can be returned for testing */
BIGNUM *p1 = NULL, *p2 = NULL;
BIGNUM *q1 = NULL, *q2 = NULL;
/* Intermediate BIGNUMS that can be input for testing */
BIGNUM *Xpout = NULL, *Xqout = NULL;
BIGNUM *Xp = NULL, *Xp1 = NULL, *Xp2 = NULL;
BIGNUM *Xq = NULL, *Xq1 = NULL, *Xq2 = NULL;
#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
if (test != NULL) {
Xp1 = test->Xp1;
Xp2 = test->Xp2;
Xq1 = test->Xq1;
Xq2 = test->Xq2;
Xp = test->Xp;
Xq = test->Xq;
p1 = test->p1;
p2 = test->p2;
q1 = test->q1;
q2 = test->q2;
}
#endif
/* (Step 1) Check key length
* NOTE: SP800-131A Rev1 Disallows key lengths of < 2048 bits for RSA
* Signature Generation and Key Agree/Transport.
*/
if (nbits < RSA_FIPS1864_MIN_KEYGEN_KEYSIZE) {
ERR_raise(ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
}
if (!ossl_rsa_check_public_exponent(e)) {
ERR_raise(ERR_LIB_RSA, RSA_R_PUB_EXPONENT_OUT_OF_RANGE);
return 0;
}
/* (Step 3) Determine strength and check rand generator strength is ok -
* this step is redundant because the generator always returns a higher
* strength than is required.
*/
BN_CTX_start(ctx);
tmp = BN_CTX_get(ctx);
Xpo = (Xpout != NULL) ? Xpout : BN_CTX_get(ctx);
Xqo = (Xqout != NULL) ? Xqout : BN_CTX_get(ctx);
if (tmp == NULL || Xpo == NULL || Xqo == NULL)
goto err;
BN_set_flags(Xpo, BN_FLG_CONSTTIME);
BN_set_flags(Xqo, BN_FLG_CONSTTIME);
if (rsa->p == NULL)
rsa->p = BN_secure_new();
if (rsa->q == NULL)
rsa->q = BN_secure_new();
if (rsa->p == NULL || rsa->q == NULL)
goto err;
BN_set_flags(rsa->p, BN_FLG_CONSTTIME);
BN_set_flags(rsa->q, BN_FLG_CONSTTIME);
/* (Step 4) Generate p, Xp */
if (!ossl_bn_rsa_fips186_4_gen_prob_primes(rsa->p, Xpo, p1, p2, Xp, Xp1, Xp2,
nbits, e, ctx, cb))
goto err;
for(;;) {
/* (Step 5) Generate q, Xq*/
if (!ossl_bn_rsa_fips186_4_gen_prob_primes(rsa->q, Xqo, q1, q2, Xq, Xq1,
Xq2, nbits, e, ctx, cb))
goto err;
/* (Step 6) |Xp - Xq| > 2^(nbitlen/2 - 100) */
ok = ossl_rsa_check_pminusq_diff(tmp, Xpo, Xqo, nbits);
if (ok < 0)
goto err;
if (ok == 0)
continue;
/* (Step 6) |p - q| > 2^(nbitlen/2 - 100) */
ok = ossl_rsa_check_pminusq_diff(tmp, rsa->p, rsa->q, nbits);
if (ok < 0)
goto err;
if (ok == 0)
continue;
break; /* successfully finished */
}
rsa->dirty_cnt++;
ret = 1;
err:
/* Zeroize any internally generated values that are not returned */
if (Xpo != Xpout)
BN_clear(Xpo);
if (Xqo != Xqout)
BN_clear(Xqo);
BN_clear(tmp);
BN_CTX_end(ctx);
return ret;
}
/*
* Validates the RSA key size based on the target strength.
* See SP800-56Br1 6.3.1.1 (Steps 1a-1b)
*
* Params:
* nbits The key size in bits.
* strength The target strength in bits. -1 means the target
* strength is unknown.
* Returns: 1 if the key size matches the target strength, or 0 otherwise.
*/
int ossl_rsa_sp800_56b_validate_strength(int nbits, int strength)
{
int s = (int)ossl_ifc_ffc_compute_security_bits(nbits);
#ifdef FIPS_MODULE
if (s < RSA_FIPS1864_MIN_KEYGEN_STRENGTH) {
ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MODULUS);
return 0;
}
#endif
if (strength != -1 && s != strength) {
ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_STRENGTH);
return 0;
}
return 1;
}
/*
* Validate that the random bit generator is of sufficient strength to generate
* a key of the specified length.
*/
static int rsa_validate_rng_strength(EVP_RAND_CTX *rng, int nbits)
{
if (rng == NULL)
return 0;
#ifdef FIPS_MODULE
/*
* This should become mainstream once similar tests are added to the other
* key generations and once there is a way to disable these checks.
*/
if (EVP_RAND_get_strength(rng) < ossl_ifc_ffc_compute_security_bits(nbits)) {
ERR_raise(ERR_LIB_RSA,
RSA_R_RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT);
return 0;
}
#endif
return 1;
}
/*
*
* Using p & q, calculate other required parameters such as n, d.
* as well as the CRT parameters dP, dQ, qInv.
*
* See SP800-56Br1
* 6.3.1.1 rsakpg1 - basic (Steps 3-4)
* 6.3.1.3 rsakpg1 - crt (Step 5)
*
* Params:
* rsa An rsa object.
* nbits The key size.
* e The public exponent.
* ctx A BN_CTX object.
* Notes:
* There is a small chance that the generated d will be too small.
* Returns: -1 = error,
* 0 = d is too small,
* 1 = success.
*/
int ossl_rsa_sp800_56b_derive_params_from_pq(RSA *rsa, int nbits,
const BIGNUM *e, BN_CTX *ctx)
{
int ret = -1;
BIGNUM *p1, *q1, *lcm, *p1q1, *gcd;
BN_CTX_start(ctx);
p1 = BN_CTX_get(ctx);
q1 = BN_CTX_get(ctx);
lcm = BN_CTX_get(ctx);
p1q1 = BN_CTX_get(ctx);
gcd = BN_CTX_get(ctx);
if (gcd == NULL)
goto err;
BN_set_flags(p1, BN_FLG_CONSTTIME);
BN_set_flags(q1, BN_FLG_CONSTTIME);
BN_set_flags(lcm, BN_FLG_CONSTTIME);
BN_set_flags(p1q1, BN_FLG_CONSTTIME);
BN_set_flags(gcd, BN_FLG_CONSTTIME);
/* LCM((p-1, q-1)) */
if (ossl_rsa_get_lcm(ctx, rsa->p, rsa->q, lcm, gcd, p1, q1, p1q1) != 1)
goto err;
/* copy e */
BN_free(rsa->e);
rsa->e = BN_dup(e);
if (rsa->e == NULL)
goto err;
BN_clear_free(rsa->d);
/* (Step 3) d = (e^-1) mod (LCM(p-1, q-1)) */
rsa->d = BN_secure_new();
if (rsa->d == NULL)
goto err;
BN_set_flags(rsa->d, BN_FLG_CONSTTIME);
if (BN_mod_inverse(rsa->d, e, lcm, ctx) == NULL)
goto err;
/* (Step 3) return an error if d is too small */
if (BN_num_bits(rsa->d) <= (nbits >> 1)) {
ret = 0;
goto err;
}
/* (Step 4) n = pq */
if (rsa->n == NULL)
rsa->n = BN_new();
if (rsa->n == NULL || !BN_mul(rsa->n, rsa->p, rsa->q, ctx))
goto err;
/* (Step 5a) dP = d mod (p-1) */
if (rsa->dmp1 == NULL)
rsa->dmp1 = BN_secure_new();
if (rsa->dmp1 == NULL)
goto err;
BN_set_flags(rsa->dmp1, BN_FLG_CONSTTIME);
if (!BN_mod(rsa->dmp1, rsa->d, p1, ctx))
goto err;
/* (Step 5b) dQ = d mod (q-1) */
if (rsa->dmq1 == NULL)
rsa->dmq1 = BN_secure_new();
if (rsa->dmq1 == NULL)
goto err;
BN_set_flags(rsa->dmq1, BN_FLG_CONSTTIME);
if (!BN_mod(rsa->dmq1, rsa->d, q1, ctx))
goto err;
/* (Step 5c) qInv = (inverse of q) mod p */
BN_free(rsa->iqmp);
rsa->iqmp = BN_secure_new();
if (rsa->iqmp == NULL)
goto err;
BN_set_flags(rsa->iqmp, BN_FLG_CONSTTIME);
if (BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx) == NULL)
goto err;
rsa->dirty_cnt++;
ret = 1;
err:
if (ret != 1) {
BN_free(rsa->e);
rsa->e = NULL;
BN_free(rsa->d);
rsa->d = NULL;
BN_free(rsa->n);
rsa->n = NULL;
BN_free(rsa->iqmp);
rsa->iqmp = NULL;
BN_free(rsa->dmq1);
rsa->dmq1 = NULL;
BN_free(rsa->dmp1);
rsa->dmp1 = NULL;
}
BN_clear(p1);
BN_clear(q1);
BN_clear(lcm);
BN_clear(p1q1);
BN_clear(gcd);
BN_CTX_end(ctx);
return ret;
}
/*
* Generate a SP800-56B RSA key.
*
* See SP800-56Br1 6.3.1 "RSA Key-Pair Generation with a Fixed Public Exponent"
* 6.3.1.1 rsakpg1 - basic
* 6.3.1.3 rsakpg1 - crt
*
* See also FIPS 186-4 Section B.3.6
* "Generation of Probable Primes with Conditions Based on Auxiliary
* Probable Primes."
*
* Params:
* rsa The rsa object.
* nbits The intended key size in bits.
* efixed The public exponent. If NULL a default of 65537 is used.
* cb An optional BIGNUM callback.
* Returns: 1 if successfully generated otherwise it returns 0.
*/
int ossl_rsa_sp800_56b_generate_key(RSA *rsa, int nbits, const BIGNUM *efixed,
BN_GENCB *cb)
{
int ret = 0;
int ok;
BN_CTX *ctx = NULL;
BIGNUM *e = NULL;
RSA_ACVP_TEST *info = NULL;
+ BIGNUM *tmp;
#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
info = rsa->acvp_test;
#endif
/* (Steps 1a-1b) : Currently ignores the strength check */
if (!ossl_rsa_sp800_56b_validate_strength(nbits, -1))
return 0;
/* Check that the RNG is capable of generating a key this large */
if (!rsa_validate_rng_strength(RAND_get0_private(rsa->libctx), nbits))
return 0;
ctx = BN_CTX_new_ex(rsa->libctx);
if (ctx == NULL)
return 0;
/* Set default if e is not passed in */
if (efixed == NULL) {
e = BN_new();
if (e == NULL || !BN_set_word(e, 65537))
goto err;
} else {
e = (BIGNUM *)efixed;
}
/* (Step 1c) fixed exponent is checked later .*/
for (;;) {
/* (Step 2) Generate prime factors */
if (!ossl_rsa_fips186_4_gen_prob_primes(rsa, info, nbits, e, ctx, cb))
goto err;
+
+ /* p>q check and skipping in case of acvp test */
+ if (info == NULL && BN_cmp(rsa->p, rsa->q) < 0) {
+ tmp = rsa->p;
+ rsa->p = rsa->q;
+ rsa->q = tmp;
+ }
+
/* (Steps 3-5) Compute params d, n, dP, dQ, qInv */
ok = ossl_rsa_sp800_56b_derive_params_from_pq(rsa, nbits, e, ctx);
if (ok < 0)
goto err;
if (ok > 0)
break;
/* Gets here if computed d is too small - so try again */
}
/* (Step 6) Do pairwise test - optional validity test has been omitted */
ret = ossl_rsa_sp800_56b_pairwise_test(rsa, ctx);
err:
if (efixed == NULL)
BN_free(e);
BN_CTX_free(ctx);
return ret;
}
/*
* See SP800-56Br1 6.3.1.3 (Step 6) Perform a pair-wise consistency test by
* verifying that: k = (k^e)^d mod n for some integer k where 1 < k < n-1.
*
* Returns 1 if the RSA key passes the pairwise test or 0 it it fails.
*/
int ossl_rsa_sp800_56b_pairwise_test(RSA *rsa, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *k, *tmp;
BN_CTX_start(ctx);
tmp = BN_CTX_get(ctx);
k = BN_CTX_get(ctx);
if (k == NULL)
goto err;
BN_set_flags(k, BN_FLG_CONSTTIME);
ret = (BN_set_word(k, 2)
&& BN_mod_exp(tmp, k, rsa->e, rsa->n, ctx)
&& BN_mod_exp(tmp, tmp, rsa->d, rsa->n, ctx)
&& BN_cmp(k, tmp) == 0);
if (ret == 0)
ERR_raise(ERR_LIB_RSA, RSA_R_PAIRWISE_TEST_FAILURE);
err:
BN_CTX_end(ctx);
return ret;
}
diff --git a/crypto/sm2/sm2_sign.c b/crypto/sm2/sm2_sign.c
index 5861f420fb66..ff5be9b73e9f 100644
--- a/crypto/sm2/sm2_sign.c
+++ b/crypto/sm2/sm2_sign.c
@@ -1,512 +1,512 @@
/*
- * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2023 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);
BN_CTX *ctx = NULL;
EVP_MD_CTX *hash = NULL;
BIGNUM *p = NULL;
BIGNUM *a = NULL;
BIGNUM *b = NULL;
BIGNUM *xG = NULL;
BIGNUM *yG = NULL;
BIGNUM *xA = NULL;
BIGNUM *yA = NULL;
int p_bytes = 0;
uint8_t *buf = NULL;
uint16_t entl = 0;
uint8_t e_byte = 0;
hash = EVP_MD_CTX_new();
ctx = BN_CTX_new_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,
EC_KEY_get0_public_key(key),
xA, yA, ctx)
|| BN_bn2binpad(xA, buf, p_bytes) < 0
|| !EVP_DigestUpdate(hash, buf, p_bytes)
|| BN_bn2binpad(yA, buf, p_bytes) < 0
|| !EVP_DigestUpdate(hash, buf, p_bytes)
|| !EVP_DigestFinal(hash, out, NULL)) {
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) {
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;
}
/*
* 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;
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);
+ sigleni = i2d_ECDSA_SIG(s, sig != NULL ? &sig : NULL);
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/ui/ui_lib.c b/crypto/ui/ui_lib.c
index 1ff8c6fa35f3..2ddf76cb5357 100644
--- a/crypto/ui/ui_lib.c
+++ b/crypto/ui/ui_lib.c
@@ -1,936 +1,940 @@
/*
- * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-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 "internal/cryptlib.h"
#include <openssl/e_os2.h>
#include <openssl/buffer.h>
#include <openssl/ui.h>
#include <openssl/err.h>
#include "ui_local.h"
UI *UI_new(void)
{
return UI_new_method(NULL);
}
UI *UI_new_method(const UI_METHOD *method)
{
UI *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
if (method == NULL)
method = UI_get_default_method();
if (method == NULL)
method = UI_null();
ret->meth = method;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data)) {
UI_free(ret);
return NULL;
}
return ret;
}
static void free_string(UI_STRING *uis)
{
if (uis->flags & OUT_STRING_FREEABLE) {
OPENSSL_free((char *)uis->out_string);
switch (uis->type) {
case UIT_BOOLEAN:
OPENSSL_free((char *)uis->_.boolean_data.action_desc);
OPENSSL_free((char *)uis->_.boolean_data.ok_chars);
OPENSSL_free((char *)uis->_.boolean_data.cancel_chars);
break;
case UIT_NONE:
case UIT_PROMPT:
case UIT_VERIFY:
case UIT_ERROR:
case UIT_INFO:
break;
}
}
OPENSSL_free(uis);
}
void UI_free(UI *ui)
{
if (ui == NULL)
return;
if ((ui->flags & UI_FLAG_DUPL_DATA) != 0) {
ui->meth->ui_destroy_data(ui, ui->user_data);
}
sk_UI_STRING_pop_free(ui->strings, free_string);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data);
CRYPTO_THREAD_lock_free(ui->lock);
OPENSSL_free(ui);
}
static int allocate_string_stack(UI *ui)
{
if (ui->strings == NULL) {
ui->strings = sk_UI_STRING_new_null();
if (ui->strings == NULL) {
return -1;
}
}
return 0;
}
static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt,
int prompt_freeable,
enum UI_string_types type,
int input_flags, char *result_buf)
{
UI_STRING *ret = NULL;
if (prompt == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_PASSED_NULL_PARAMETER);
} else if ((type == UIT_PROMPT || type == UIT_VERIFY
|| type == UIT_BOOLEAN) && result_buf == NULL) {
ERR_raise(ERR_LIB_UI, UI_R_NO_RESULT_BUFFER);
} else if ((ret = OPENSSL_zalloc(sizeof(*ret))) != NULL) {
ret->out_string = prompt;
ret->flags = prompt_freeable ? OUT_STRING_FREEABLE : 0;
ret->input_flags = input_flags;
ret->type = type;
ret->result_buf = result_buf;
}
return ret;
}
static int general_allocate_string(UI *ui, const char *prompt,
int prompt_freeable,
enum UI_string_types type, int input_flags,
char *result_buf, int minsize, int maxsize,
const char *test_buf)
{
int ret = -1;
UI_STRING *s = general_allocate_prompt(ui, prompt, prompt_freeable,
type, input_flags, result_buf);
if (s != NULL) {
if (allocate_string_stack(ui) >= 0) {
s->_.string_data.result_minsize = minsize;
s->_.string_data.result_maxsize = maxsize;
s->_.string_data.test_buf = test_buf;
ret = sk_UI_STRING_push(ui->strings, s);
/* sk_push() returns 0 on error. Let's adapt that */
if (ret <= 0) {
ret--;
free_string(s);
}
} else
free_string(s);
}
return ret;
}
static int general_allocate_boolean(UI *ui,
const char *prompt,
const char *action_desc,
const char *ok_chars,
const char *cancel_chars,
int prompt_freeable,
enum UI_string_types type,
int input_flags, char *result_buf)
{
int ret = -1;
UI_STRING *s;
const char *p;
if (ok_chars == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_PASSED_NULL_PARAMETER);
} else if (cancel_chars == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_PASSED_NULL_PARAMETER);
} else {
for (p = ok_chars; *p != '\0'; p++) {
if (strchr(cancel_chars, *p) != NULL) {
ERR_raise(ERR_LIB_UI, UI_R_COMMON_OK_AND_CANCEL_CHARACTERS);
}
}
s = general_allocate_prompt(ui, prompt, prompt_freeable,
type, input_flags, result_buf);
if (s != NULL) {
if (allocate_string_stack(ui) >= 0) {
s->_.boolean_data.action_desc = action_desc;
s->_.boolean_data.ok_chars = ok_chars;
s->_.boolean_data.cancel_chars = cancel_chars;
ret = sk_UI_STRING_push(ui->strings, s);
/*
* sk_push() returns 0 on error. Let's adapt that
*/
if (ret <= 0) {
ret--;
free_string(s);
}
} else
free_string(s);
}
}
return ret;
}
/*
* Returns the index to the place in the stack or -1 for error. Uses a
* direct reference to the prompt.
*/
int UI_add_input_string(UI *ui, const char *prompt, int flags,
char *result_buf, int minsize, int maxsize)
{
return general_allocate_string(ui, prompt, 0,
UIT_PROMPT, flags, result_buf, minsize,
maxsize, NULL);
}
/* Same as UI_add_input_string(), excepts it takes a copy of the prompt */
int UI_dup_input_string(UI *ui, const char *prompt, int flags,
char *result_buf, int minsize, int maxsize)
{
char *prompt_copy = NULL;
if (prompt != NULL) {
prompt_copy = OPENSSL_strdup(prompt);
if (prompt_copy == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return 0;
}
}
return general_allocate_string(ui, prompt_copy, 1,
UIT_PROMPT, flags, result_buf, minsize,
maxsize, NULL);
}
int UI_add_verify_string(UI *ui, const char *prompt, int flags,
char *result_buf, int minsize, int maxsize,
const char *test_buf)
{
return general_allocate_string(ui, prompt, 0,
UIT_VERIFY, flags, result_buf, minsize,
maxsize, test_buf);
}
int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
char *result_buf, int minsize, int maxsize,
const char *test_buf)
{
char *prompt_copy = NULL;
if (prompt != NULL) {
prompt_copy = OPENSSL_strdup(prompt);
if (prompt_copy == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return -1;
}
}
return general_allocate_string(ui, prompt_copy, 1,
UIT_VERIFY, flags, result_buf, minsize,
maxsize, test_buf);
}
int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc,
const char *ok_chars, const char *cancel_chars,
int flags, char *result_buf)
{
return general_allocate_boolean(ui, prompt, action_desc,
ok_chars, cancel_chars, 0, UIT_BOOLEAN,
flags, result_buf);
}
int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
const char *ok_chars, const char *cancel_chars,
int flags, char *result_buf)
{
char *prompt_copy = NULL;
char *action_desc_copy = NULL;
char *ok_chars_copy = NULL;
char *cancel_chars_copy = NULL;
if (prompt != NULL) {
prompt_copy = OPENSSL_strdup(prompt);
if (prompt_copy == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if (action_desc != NULL) {
action_desc_copy = OPENSSL_strdup(action_desc);
if (action_desc_copy == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if (ok_chars != NULL) {
ok_chars_copy = OPENSSL_strdup(ok_chars);
if (ok_chars_copy == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if (cancel_chars != NULL) {
cancel_chars_copy = OPENSSL_strdup(cancel_chars);
if (cancel_chars_copy == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
goto err;
}
}
return general_allocate_boolean(ui, prompt_copy, action_desc_copy,
ok_chars_copy, cancel_chars_copy, 1,
UIT_BOOLEAN, flags, result_buf);
err:
OPENSSL_free(prompt_copy);
OPENSSL_free(action_desc_copy);
OPENSSL_free(ok_chars_copy);
OPENSSL_free(cancel_chars_copy);
return -1;
}
int UI_add_info_string(UI *ui, const char *text)
{
return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0,
NULL);
}
int UI_dup_info_string(UI *ui, const char *text)
{
char *text_copy = NULL;
if (text != NULL) {
text_copy = OPENSSL_strdup(text);
if (text_copy == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return -1;
}
}
return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL,
0, 0, NULL);
}
int UI_add_error_string(UI *ui, const char *text)
{
return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0,
NULL);
}
int UI_dup_error_string(UI *ui, const char *text)
{
char *text_copy = NULL;
if (text != NULL) {
text_copy = OPENSSL_strdup(text);
if (text_copy == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return -1;
}
}
return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL,
0, 0, NULL);
}
char *UI_construct_prompt(UI *ui, const char *phrase_desc,
const char *object_name)
{
char *prompt = NULL;
if (ui != NULL && ui->meth != NULL && ui->meth->ui_construct_prompt != NULL)
prompt = ui->meth->ui_construct_prompt(ui, phrase_desc, object_name);
else {
char prompt1[] = "Enter ";
char prompt2[] = " for ";
char prompt3[] = ":";
int len = 0;
if (phrase_desc == NULL)
return NULL;
len = sizeof(prompt1) - 1 + strlen(phrase_desc);
if (object_name != NULL)
len += sizeof(prompt2) - 1 + strlen(object_name);
len += sizeof(prompt3) - 1;
if ((prompt = OPENSSL_malloc(len + 1)) == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return NULL;
}
OPENSSL_strlcpy(prompt, prompt1, len + 1);
OPENSSL_strlcat(prompt, phrase_desc, len + 1);
if (object_name != NULL) {
OPENSSL_strlcat(prompt, prompt2, len + 1);
OPENSSL_strlcat(prompt, object_name, len + 1);
}
OPENSSL_strlcat(prompt, prompt3, len + 1);
}
return prompt;
}
void *UI_add_user_data(UI *ui, void *user_data)
{
void *old_data = ui->user_data;
if ((ui->flags & UI_FLAG_DUPL_DATA) != 0) {
ui->meth->ui_destroy_data(ui, old_data);
old_data = NULL;
}
ui->user_data = user_data;
ui->flags &= ~UI_FLAG_DUPL_DATA;
return old_data;
}
int UI_dup_user_data(UI *ui, void *user_data)
{
void *duplicate = NULL;
if (ui->meth->ui_duplicate_data == NULL
|| ui->meth->ui_destroy_data == NULL) {
ERR_raise(ERR_LIB_UI, UI_R_USER_DATA_DUPLICATION_UNSUPPORTED);
return -1;
}
duplicate = ui->meth->ui_duplicate_data(ui, user_data);
if (duplicate == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return -1;
}
(void)UI_add_user_data(ui, duplicate);
ui->flags |= UI_FLAG_DUPL_DATA;
return 0;
}
void *UI_get0_user_data(UI *ui)
{
return ui->user_data;
}
const char *UI_get0_result(UI *ui, int i)
{
if (i < 0) {
ERR_raise(ERR_LIB_UI, UI_R_INDEX_TOO_SMALL);
return NULL;
}
if (i >= sk_UI_STRING_num(ui->strings)) {
ERR_raise(ERR_LIB_UI, UI_R_INDEX_TOO_LARGE);
return NULL;
}
return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i));
}
int UI_get_result_length(UI *ui, int i)
{
if (i < 0) {
ERR_raise(ERR_LIB_UI, UI_R_INDEX_TOO_SMALL);
return -1;
}
if (i >= sk_UI_STRING_num(ui->strings)) {
ERR_raise(ERR_LIB_UI, UI_R_INDEX_TOO_LARGE);
return -1;
}
return UI_get_result_string_length(sk_UI_STRING_value(ui->strings, i));
}
static int print_error(const char *str, size_t len, UI *ui)
{
UI_STRING uis;
memset(&uis, 0, sizeof(uis));
uis.type = UIT_ERROR;
uis.out_string = str;
if (ui->meth->ui_write_string != NULL
&& ui->meth->ui_write_string(ui, &uis) <= 0)
return -1;
return 0;
}
int UI_process(UI *ui)
{
int i, ok = 0;
const char *state = "processing";
if (ui->meth->ui_open_session != NULL
&& ui->meth->ui_open_session(ui) <= 0) {
state = "opening session";
ok = -1;
goto err;
}
if (ui->flags & UI_FLAG_PRINT_ERRORS)
ERR_print_errors_cb((int (*)(const char *, size_t, void *))
print_error, (void *)ui);
for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) {
if (ui->meth->ui_write_string != NULL
&& (ui->meth->ui_write_string(ui,
sk_UI_STRING_value(ui->strings, i))
<= 0))
{
state = "writing strings";
ok = -1;
goto err;
}
}
if (ui->meth->ui_flush != NULL)
switch (ui->meth->ui_flush(ui)) {
case -1: /* Interrupt/Cancel/something... */
ui->flags &= ~UI_FLAG_REDOABLE;
ok = -2;
goto err;
case 0: /* Errors */
state = "flushing";
ok = -1;
goto err;
default: /* Success */
ok = 0;
break;
}
for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) {
if (ui->meth->ui_read_string != NULL) {
switch (ui->meth->ui_read_string(ui,
sk_UI_STRING_value(ui->strings,
i))) {
case -1: /* Interrupt/Cancel/something... */
ui->flags &= ~UI_FLAG_REDOABLE;
ok = -2;
goto err;
case 0: /* Errors */
state = "reading strings";
ok = -1;
goto err;
default: /* Success */
ok = 0;
break;
}
+ } else {
+ ui->flags &= ~UI_FLAG_REDOABLE;
+ ok = -2;
+ goto err;
}
}
state = NULL;
err:
if (ui->meth->ui_close_session != NULL
&& ui->meth->ui_close_session(ui) <= 0) {
if (state == NULL)
state = "closing session";
ok = -1;
}
if (ok == -1)
ERR_raise_data(ERR_LIB_UI, UI_R_PROCESSING_ERROR, "while %s", state);
return ok;
}
int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void))
{
if (ui == NULL) {
ERR_raise(ERR_LIB_UI, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
switch (cmd) {
case UI_CTRL_PRINT_ERRORS:
{
int save_flag = ! !(ui->flags & UI_FLAG_PRINT_ERRORS);
if (i)
ui->flags |= UI_FLAG_PRINT_ERRORS;
else
ui->flags &= ~UI_FLAG_PRINT_ERRORS;
return save_flag;
}
case UI_CTRL_IS_REDOABLE:
return ! !(ui->flags & UI_FLAG_REDOABLE);
default:
break;
}
ERR_raise(ERR_LIB_UI, UI_R_UNKNOWN_CONTROL_COMMAND);
return -1;
}
int UI_set_ex_data(UI *r, int idx, void *arg)
{
return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
}
void *UI_get_ex_data(const UI *r, int idx)
{
return CRYPTO_get_ex_data(&r->ex_data, idx);
}
const UI_METHOD *UI_get_method(UI *ui)
{
return ui->meth;
}
const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth)
{
ui->meth = meth;
return ui->meth;
}
UI_METHOD *UI_create_method(const char *name)
{
UI_METHOD *ui_method = NULL;
if ((ui_method = OPENSSL_zalloc(sizeof(*ui_method))) == NULL
|| (ui_method->name = OPENSSL_strdup(name)) == NULL
|| !CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI_METHOD, ui_method,
&ui_method->ex_data)) {
if (ui_method)
OPENSSL_free(ui_method->name);
OPENSSL_free(ui_method);
ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE);
return NULL;
}
return ui_method;
}
/*
* BIG FSCKING WARNING!!!! If you use this on a statically allocated method
* (that is, it hasn't been allocated using UI_create_method(), you deserve
* anything Murphy can throw at you and more! You have been warned.
*/
void UI_destroy_method(UI_METHOD *ui_method)
{
if (ui_method == NULL)
return;
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI_METHOD, ui_method,
&ui_method->ex_data);
OPENSSL_free(ui_method->name);
ui_method->name = NULL;
OPENSSL_free(ui_method);
}
int UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui))
{
if (method != NULL) {
method->ui_open_session = opener;
return 0;
}
return -1;
}
int UI_method_set_writer(UI_METHOD *method,
int (*writer) (UI *ui, UI_STRING *uis))
{
if (method != NULL) {
method->ui_write_string = writer;
return 0;
}
return -1;
}
int UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui))
{
if (method != NULL) {
method->ui_flush = flusher;
return 0;
}
return -1;
}
int UI_method_set_reader(UI_METHOD *method,
int (*reader) (UI *ui, UI_STRING *uis))
{
if (method != NULL) {
method->ui_read_string = reader;
return 0;
}
return -1;
}
int UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui))
{
if (method != NULL) {
method->ui_close_session = closer;
return 0;
}
return -1;
}
int UI_method_set_data_duplicator(UI_METHOD *method,
void *(*duplicator) (UI *ui, void *ui_data),
void (*destructor)(UI *ui, void *ui_data))
{
if (method != NULL) {
method->ui_duplicate_data = duplicator;
method->ui_destroy_data = destructor;
return 0;
}
return -1;
}
int UI_method_set_prompt_constructor(UI_METHOD *method,
char *(*prompt_constructor) (UI *ui,
const char *,
const char *))
{
if (method != NULL) {
method->ui_construct_prompt = prompt_constructor;
return 0;
}
return -1;
}
int UI_method_set_ex_data(UI_METHOD *method, int idx, void *data)
{
return CRYPTO_set_ex_data(&method->ex_data, idx, data);
}
int (*UI_method_get_opener(const UI_METHOD *method)) (UI *)
{
if (method != NULL)
return method->ui_open_session;
return NULL;
}
int (*UI_method_get_writer(const UI_METHOD *method)) (UI *, UI_STRING *)
{
if (method != NULL)
return method->ui_write_string;
return NULL;
}
int (*UI_method_get_flusher(const UI_METHOD *method)) (UI *)
{
if (method != NULL)
return method->ui_flush;
return NULL;
}
int (*UI_method_get_reader(const UI_METHOD *method)) (UI *, UI_STRING *)
{
if (method != NULL)
return method->ui_read_string;
return NULL;
}
int (*UI_method_get_closer(const UI_METHOD *method)) (UI *)
{
if (method != NULL)
return method->ui_close_session;
return NULL;
}
char *(*UI_method_get_prompt_constructor(const UI_METHOD *method))
(UI *, const char *, const char *)
{
if (method != NULL)
return method->ui_construct_prompt;
return NULL;
}
void *(*UI_method_get_data_duplicator(const UI_METHOD *method)) (UI *, void *)
{
if (method != NULL)
return method->ui_duplicate_data;
return NULL;
}
void (*UI_method_get_data_destructor(const UI_METHOD *method)) (UI *, void *)
{
if (method != NULL)
return method->ui_destroy_data;
return NULL;
}
const void *UI_method_get_ex_data(const UI_METHOD *method, int idx)
{
return CRYPTO_get_ex_data(&method->ex_data, idx);
}
enum UI_string_types UI_get_string_type(UI_STRING *uis)
{
return uis->type;
}
int UI_get_input_flags(UI_STRING *uis)
{
return uis->input_flags;
}
const char *UI_get0_output_string(UI_STRING *uis)
{
return uis->out_string;
}
const char *UI_get0_action_string(UI_STRING *uis)
{
switch (uis->type) {
case UIT_BOOLEAN:
return uis->_.boolean_data.action_desc;
case UIT_PROMPT:
case UIT_NONE:
case UIT_VERIFY:
case UIT_INFO:
case UIT_ERROR:
break;
}
return NULL;
}
const char *UI_get0_result_string(UI_STRING *uis)
{
switch (uis->type) {
case UIT_PROMPT:
case UIT_VERIFY:
return uis->result_buf;
case UIT_NONE:
case UIT_BOOLEAN:
case UIT_INFO:
case UIT_ERROR:
break;
}
return NULL;
}
int UI_get_result_string_length(UI_STRING *uis)
{
switch (uis->type) {
case UIT_PROMPT:
case UIT_VERIFY:
return uis->result_len;
case UIT_NONE:
case UIT_BOOLEAN:
case UIT_INFO:
case UIT_ERROR:
break;
}
return -1;
}
const char *UI_get0_test_string(UI_STRING *uis)
{
switch (uis->type) {
case UIT_VERIFY:
return uis->_.string_data.test_buf;
case UIT_NONE:
case UIT_BOOLEAN:
case UIT_INFO:
case UIT_ERROR:
case UIT_PROMPT:
break;
}
return NULL;
}
int UI_get_result_minsize(UI_STRING *uis)
{
switch (uis->type) {
case UIT_PROMPT:
case UIT_VERIFY:
return uis->_.string_data.result_minsize;
case UIT_NONE:
case UIT_INFO:
case UIT_ERROR:
case UIT_BOOLEAN:
break;
}
return -1;
}
int UI_get_result_maxsize(UI_STRING *uis)
{
switch (uis->type) {
case UIT_PROMPT:
case UIT_VERIFY:
return uis->_.string_data.result_maxsize;
case UIT_NONE:
case UIT_INFO:
case UIT_ERROR:
case UIT_BOOLEAN:
break;
}
return -1;
}
int UI_set_result(UI *ui, UI_STRING *uis, const char *result)
{
return UI_set_result_ex(ui, uis, result, strlen(result));
}
int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len)
{
ui->flags &= ~UI_FLAG_REDOABLE;
switch (uis->type) {
case UIT_PROMPT:
case UIT_VERIFY:
if (len < uis->_.string_data.result_minsize) {
ui->flags |= UI_FLAG_REDOABLE;
ERR_raise_data(ERR_LIB_UI, UI_R_RESULT_TOO_SMALL,
"You must type in %d to %d characters",
uis->_.string_data.result_minsize,
uis->_.string_data.result_maxsize);
return -1;
}
if (len > uis->_.string_data.result_maxsize) {
ui->flags |= UI_FLAG_REDOABLE;
ERR_raise_data(ERR_LIB_UI, UI_R_RESULT_TOO_LARGE,
"You must type in %d to %d characters",
uis->_.string_data.result_minsize,
uis->_.string_data.result_maxsize);
return -1;
}
if (uis->result_buf == NULL) {
ERR_raise(ERR_LIB_UI, UI_R_NO_RESULT_BUFFER);
return -1;
}
memcpy(uis->result_buf, result, len);
if (len <= uis->_.string_data.result_maxsize)
uis->result_buf[len] = '\0';
uis->result_len = len;
break;
case UIT_BOOLEAN:
{
const char *p;
if (uis->result_buf == NULL) {
ERR_raise(ERR_LIB_UI, UI_R_NO_RESULT_BUFFER);
return -1;
}
uis->result_buf[0] = '\0';
for (p = result; *p; p++) {
if (strchr(uis->_.boolean_data.ok_chars, *p)) {
uis->result_buf[0] = uis->_.boolean_data.ok_chars[0];
break;
}
if (strchr(uis->_.boolean_data.cancel_chars, *p)) {
uis->result_buf[0] = uis->_.boolean_data.cancel_chars[0];
break;
}
}
}
case UIT_NONE:
case UIT_INFO:
case UIT_ERROR:
break;
}
return 0;
}
diff --git a/crypto/ui/ui_util.c b/crypto/ui/ui_util.c
index 80297969ab1d..59b00b225adf 100644
--- a/crypto/ui/ui_util.c
+++ b/crypto/ui/ui_util.c
@@ -1,165 +1,163 @@
/*
- * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 = 0;
+ 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);
}
- if (ok > 0)
- ok = 0;
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];
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 (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/x509/pcy_local.h b/crypto/x509/pcy_local.h
index 18b53cc09ebf..523f3e35feeb 100644
--- a/crypto/x509/pcy_local.h
+++ b/crypto/x509/pcy_local.h
@@ -1,165 +1,171 @@
/*
- * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-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
*/
typedef struct X509_POLICY_DATA_st X509_POLICY_DATA;
DEFINE_STACK_OF(X509_POLICY_DATA)
/* Internal structures */
/*
* This structure and the field names correspond to the Policy 'node' of
* RFC3280. NB this structure contains no pointers to parent or child data:
* X509_POLICY_NODE contains that. This means that the main policy data can
* be kept static and cached with the certificate.
*/
struct X509_POLICY_DATA_st {
unsigned int flags;
/* Policy OID and qualifiers for this data */
ASN1_OBJECT *valid_policy;
STACK_OF(POLICYQUALINFO) *qualifier_set;
STACK_OF(ASN1_OBJECT) *expected_policy_set;
};
/* X509_POLICY_DATA flags values */
/*
* This flag indicates the structure has been mapped using a policy mapping
* extension. If policy mapping is not active its references get deleted.
*/
#define POLICY_DATA_FLAG_MAPPED 0x1
/*
* This flag indicates the data doesn't correspond to a policy in Certificate
* Policies: it has been mapped to any policy.
*/
#define POLICY_DATA_FLAG_MAPPED_ANY 0x2
/* AND with flags to see if any mapping has occurred */
#define POLICY_DATA_FLAG_MAP_MASK 0x3
/* qualifiers are shared and shouldn't be freed */
#define POLICY_DATA_FLAG_SHARED_QUALIFIERS 0x4
/* Parent node is an extra node and should be freed */
#define POLICY_DATA_FLAG_EXTRA_NODE 0x8
/* Corresponding CertificatePolicies is critical */
#define POLICY_DATA_FLAG_CRITICAL 0x10
/* This structure is cached with a certificate */
struct X509_POLICY_CACHE_st {
/* anyPolicy data or NULL if no anyPolicy */
X509_POLICY_DATA *anyPolicy;
/* other policy data */
STACK_OF(X509_POLICY_DATA) *data;
/* If InhibitAnyPolicy present this is its value or -1 if absent. */
long any_skip;
/*
* If policyConstraints and requireExplicitPolicy present this is its
* value or -1 if absent.
*/
long explicit_skip;
/*
* If policyConstraints and policyMapping present this is its value or -1
* if absent.
*/
long map_skip;
};
/*
* #define POLICY_CACHE_FLAG_CRITICAL POLICY_DATA_FLAG_CRITICAL
*/
/* This structure represents the relationship between nodes */
struct X509_POLICY_NODE_st {
/* node data this refers to */
const X509_POLICY_DATA *data;
/* Parent node */
X509_POLICY_NODE *parent;
/* Number of child nodes */
int nchild;
};
struct X509_POLICY_LEVEL_st {
/* Cert for this level */
X509 *cert;
/* nodes at this level */
STACK_OF(X509_POLICY_NODE) *nodes;
/* anyPolicy node */
X509_POLICY_NODE *anyPolicy;
/* Extra data */
/*
* STACK_OF(X509_POLICY_DATA) *extra_data;
*/
unsigned int flags;
};
struct X509_POLICY_TREE_st {
+ /* The number of nodes in the tree */
+ size_t node_count;
+ /* The maximum number of nodes in the tree */
+ size_t node_maximum;
+
/* This is the tree 'level' data */
X509_POLICY_LEVEL *levels;
int nlevel;
/*
* Extra policy data when additional nodes (not from the certificate) are
* required.
*/
STACK_OF(X509_POLICY_DATA) *extra_data;
/* This is the authority constrained policy set */
STACK_OF(X509_POLICY_NODE) *auth_policies;
STACK_OF(X509_POLICY_NODE) *user_policies;
unsigned int flags;
};
/* Set if anyPolicy present in user policies */
#define POLICY_FLAG_ANY_POLICY 0x2
/* Useful macros */
#define node_data_critical(data) (data->flags & POLICY_DATA_FLAG_CRITICAL)
#define node_critical(node) node_data_critical(node->data)
/* Internal functions */
X509_POLICY_DATA *ossl_policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *id,
int crit);
void ossl_policy_data_free(X509_POLICY_DATA *data);
X509_POLICY_DATA *ossl_policy_cache_find_data(const X509_POLICY_CACHE *cache,
const ASN1_OBJECT *id);
int ossl_policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps);
STACK_OF(X509_POLICY_NODE) *ossl_policy_node_cmp_new(void);
void ossl_policy_cache_free(X509_POLICY_CACHE *cache);
X509_POLICY_NODE *ossl_policy_level_find_node(const X509_POLICY_LEVEL *level,
const X509_POLICY_NODE *parent,
const ASN1_OBJECT *id);
X509_POLICY_NODE *ossl_policy_tree_find_sk(STACK_OF(X509_POLICY_NODE) *sk,
const ASN1_OBJECT *id);
X509_POLICY_NODE *ossl_policy_level_add_node(X509_POLICY_LEVEL *level,
X509_POLICY_DATA *data,
X509_POLICY_NODE *parent,
- X509_POLICY_TREE *tree);
+ X509_POLICY_TREE *tree,
+ int extra_data);
void ossl_policy_node_free(X509_POLICY_NODE *node);
int ossl_policy_node_match(const X509_POLICY_LEVEL *lvl,
const X509_POLICY_NODE *node, const ASN1_OBJECT *oid);
const X509_POLICY_CACHE *ossl_policy_cache_set(X509 *x);
diff --git a/crypto/x509/pcy_node.c b/crypto/x509/pcy_node.c
index 9d9a7ea1799c..9b77e6e95e05 100644
--- a/crypto/x509/pcy_node.c
+++ b/crypto/x509/pcy_node.c
@@ -1,147 +1,161 @@
/*
- * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-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/asn1.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include "pcy_local.h"
static int node_cmp(const X509_POLICY_NODE *const *a,
const X509_POLICY_NODE *const *b)
{
return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy);
}
STACK_OF(X509_POLICY_NODE) *ossl_policy_node_cmp_new(void)
{
return sk_X509_POLICY_NODE_new(node_cmp);
}
X509_POLICY_NODE *ossl_policy_tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes,
const ASN1_OBJECT *id)
{
X509_POLICY_DATA n;
X509_POLICY_NODE l;
int idx;
n.valid_policy = (ASN1_OBJECT *)id;
l.data = &n;
idx = sk_X509_POLICY_NODE_find(nodes, &l);
return sk_X509_POLICY_NODE_value(nodes, idx);
}
X509_POLICY_NODE *ossl_policy_level_find_node(const X509_POLICY_LEVEL *level,
const X509_POLICY_NODE *parent,
const ASN1_OBJECT *id)
{
X509_POLICY_NODE *node;
int i;
for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) {
node = sk_X509_POLICY_NODE_value(level->nodes, i);
if (node->parent == parent) {
if (!OBJ_cmp(node->data->valid_policy, id))
return node;
}
}
return NULL;
}
X509_POLICY_NODE *ossl_policy_level_add_node(X509_POLICY_LEVEL *level,
X509_POLICY_DATA *data,
X509_POLICY_NODE *parent,
- X509_POLICY_TREE *tree)
+ X509_POLICY_TREE *tree,
+ int extra_data)
{
X509_POLICY_NODE *node;
+ /* Verify that the tree isn't too large. This mitigates CVE-2023-0464 */
+ if (tree->node_maximum > 0 && tree->node_count >= tree->node_maximum)
+ return NULL;
+
node = OPENSSL_zalloc(sizeof(*node));
if (node == NULL) {
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return NULL;
}
node->data = data;
node->parent = parent;
- if (level) {
+ if (level != NULL) {
if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
if (level->anyPolicy)
goto node_error;
level->anyPolicy = node;
} else {
if (level->nodes == NULL)
level->nodes = ossl_policy_node_cmp_new();
if (level->nodes == NULL) {
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto node_error;
}
if (!sk_X509_POLICY_NODE_push(level->nodes, node)) {
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
goto node_error;
}
}
}
- if (tree) {
+ if (extra_data) {
if (tree->extra_data == NULL)
tree->extra_data = sk_X509_POLICY_DATA_new_null();
if (tree->extra_data == NULL){
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
- goto node_error;
+ goto extra_data_error;
}
if (!sk_X509_POLICY_DATA_push(tree->extra_data, data)) {
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
- goto node_error;
+ goto extra_data_error;
}
}
+ tree->node_count++;
if (parent)
parent->nchild++;
return node;
+ extra_data_error:
+ if (level != NULL) {
+ if (level->anyPolicy == node)
+ level->anyPolicy = NULL;
+ else
+ (void) sk_X509_POLICY_NODE_pop(level->nodes);
+ }
+
node_error:
ossl_policy_node_free(node);
return NULL;
}
void ossl_policy_node_free(X509_POLICY_NODE *node)
{
OPENSSL_free(node);
}
/*
* See if a policy node matches a policy OID. If mapping enabled look through
* expected policy set otherwise just valid policy.
*/
int ossl_policy_node_match(const X509_POLICY_LEVEL *lvl,
const X509_POLICY_NODE *node, const ASN1_OBJECT *oid)
{
int i;
ASN1_OBJECT *policy_oid;
const X509_POLICY_DATA *x = node->data;
if ((lvl->flags & X509_V_FLAG_INHIBIT_MAP)
|| !(x->flags & POLICY_DATA_FLAG_MAP_MASK)) {
if (!OBJ_cmp(x->valid_policy, oid))
return 1;
return 0;
}
for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++) {
policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i);
if (!OBJ_cmp(policy_oid, oid))
return 1;
}
return 0;
}
diff --git a/crypto/x509/pcy_tree.c b/crypto/x509/pcy_tree.c
index fa45da5117a1..2012810303ed 100644
--- a/crypto/x509/pcy_tree.c
+++ b/crypto/x509/pcy_tree.c
@@ -1,697 +1,723 @@
/*
- * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-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/trace.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "pcy_local.h"
+/*
+ * If the maximum number of nodes in the policy tree isn't defined, set it to
+ * a generous default of 1000 nodes.
+ *
+ * Defining this to be zero means unlimited policy tree growth which opens the
+ * door on CVE-2023-0464.
+ */
+#ifndef OPENSSL_POLICY_TREE_NODES_MAX
+# define OPENSSL_POLICY_TREE_NODES_MAX 1000
+#endif
+
+static void exnode_free(X509_POLICY_NODE *node);
+
static void expected_print(BIO *channel,
X509_POLICY_LEVEL *lev, X509_POLICY_NODE *node,
int indent)
{
if ((lev->flags & X509_V_FLAG_INHIBIT_MAP)
|| !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
BIO_puts(channel, " Not Mapped\n");
else {
int i;
STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
ASN1_OBJECT *oid;
BIO_puts(channel, " Expected: ");
for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) {
oid = sk_ASN1_OBJECT_value(pset, i);
if (i)
BIO_puts(channel, ", ");
i2a_ASN1_OBJECT(channel, oid);
}
BIO_puts(channel, "\n");
}
}
static void tree_print(BIO *channel,
char *str, X509_POLICY_TREE *tree,
X509_POLICY_LEVEL *curr)
{
X509_POLICY_LEVEL *plev;
if (!curr)
curr = tree->levels + tree->nlevel;
else
curr++;
BIO_printf(channel, "Level print after %s\n", str);
BIO_printf(channel, "Printing Up to Level %ld\n",
(long)(curr - tree->levels));
for (plev = tree->levels; plev != curr; plev++) {
int i;
BIO_printf(channel, "Level %ld, flags = %x\n",
(long)(plev - tree->levels), plev->flags);
for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) {
X509_POLICY_NODE *node =
sk_X509_POLICY_NODE_value(plev->nodes, i);
X509_POLICY_NODE_print(channel, node, 2);
expected_print(channel, plev, node, 2);
BIO_printf(channel, " Flags: %x\n", node->data->flags);
}
if (plev->anyPolicy)
X509_POLICY_NODE_print(channel, plev->anyPolicy, 2);
}
}
#define TREE_PRINT(str, tree, curr) \
OSSL_TRACE_BEGIN(X509V3_POLICY) { \
tree_print(trc_out, "before tree_prune()", tree, curr); \
} OSSL_TRACE_END(X509V3_POLICY)
/*-
* Return value: <= 0 on error, or positive bit mask:
*
* X509_PCY_TREE_VALID: valid tree
* X509_PCY_TREE_EMPTY: empty tree (including bare TA case)
* X509_PCY_TREE_EXPLICIT: explicit policy required
*/
static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
unsigned int flags)
{
X509_POLICY_TREE *tree;
X509_POLICY_LEVEL *level;
const X509_POLICY_CACHE *cache;
X509_POLICY_DATA *data = NULL;
int ret = X509_PCY_TREE_VALID;
int n = sk_X509_num(certs) - 1; /* RFC5280 paths omit the TA */
int explicit_policy = (flags & X509_V_FLAG_EXPLICIT_POLICY) ? 0 : n+1;
int any_skip = (flags & X509_V_FLAG_INHIBIT_ANY) ? 0 : n+1;
int map_skip = (flags & X509_V_FLAG_INHIBIT_MAP) ? 0 : n+1;
int i;
*ptree = NULL;
/* Can't do anything with just a trust anchor */
if (n == 0)
return X509_PCY_TREE_EMPTY;
/*
* First setup the policy cache in all n non-TA certificates, this will be
* used in X509_verify_cert() which will invoke the verify callback for all
* certificates with invalid policy extensions.
*/
for (i = n - 1; i >= 0; i--) {
X509 *x = sk_X509_value(certs, i);
/* Call for side-effect of computing hash and caching extensions */
X509_check_purpose(x, -1, 0);
/* If cache is NULL, likely ENOMEM: return immediately */
if (ossl_policy_cache_set(x) == NULL)
return X509_PCY_TREE_INTERNAL;
}
/*
* At this point check for invalid policies and required explicit policy.
* Note that the explicit_policy counter is a count-down to zero, with the
* requirement kicking in if and once it does that. The counter is
* decremented for every non-self-issued certificate in the path, but may
* be further reduced by policy constraints in a non-leaf certificate.
*
* The ultimate policy set is the intersection of all the policies along
* the path, if we hit a certificate with an empty policy set, and explicit
* policy is required we're done.
*/
for (i = n - 1;
i >= 0 && (explicit_policy > 0 || (ret & X509_PCY_TREE_EMPTY) == 0);
i--) {
X509 *x = sk_X509_value(certs, i);
uint32_t ex_flags = X509_get_extension_flags(x);
/* All the policies are already cached, we can return early */
if (ex_flags & EXFLAG_INVALID_POLICY)
return X509_PCY_TREE_INVALID;
/* Access the cache which we now know exists */
cache = ossl_policy_cache_set(x);
if ((ret & X509_PCY_TREE_VALID) && cache->data == NULL)
ret = X509_PCY_TREE_EMPTY;
if (explicit_policy > 0) {
if (!(ex_flags & EXFLAG_SI))
explicit_policy--;
if ((cache->explicit_skip >= 0)
&& (cache->explicit_skip < explicit_policy))
explicit_policy = cache->explicit_skip;
}
}
if (explicit_policy == 0)
ret |= X509_PCY_TREE_EXPLICIT;
if ((ret & X509_PCY_TREE_VALID) == 0)
return ret;
/* If we get this far initialize the tree */
if ((tree = OPENSSL_zalloc(sizeof(*tree))) == NULL) {
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return X509_PCY_TREE_INTERNAL;
}
+ /* Limit the growth of the tree to mitigate CVE-2023-0464 */
+ tree->node_maximum = OPENSSL_POLICY_TREE_NODES_MAX;
+
/*
* http://tools.ietf.org/html/rfc5280#section-6.1.2, figure 3.
*
* The top level is implicitly for the trust anchor with valid expected
* policies of anyPolicy. (RFC 5280 has the TA at depth 0 and the leaf at
* depth n, we have the leaf at depth 0 and the TA at depth n).
*/
if ((tree->levels = OPENSSL_zalloc(sizeof(*tree->levels)*(n+1))) == NULL) {
OPENSSL_free(tree);
ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
return X509_PCY_TREE_INTERNAL;
}
tree->nlevel = n+1;
level = tree->levels;
if ((data = ossl_policy_data_new(NULL,
OBJ_nid2obj(NID_any_policy), 0)) == NULL)
goto bad_tree;
- if (ossl_policy_level_add_node(level, data, NULL, tree) == NULL) {
+ if (ossl_policy_level_add_node(level, data, NULL, tree, 1) == NULL) {
ossl_policy_data_free(data);
goto bad_tree;
}
/*
* In this pass initialize all the tree levels and whether anyPolicy and
* policy mapping are inhibited at each level.
*/
for (i = n - 1; i >= 0; i--) {
X509 *x = sk_X509_value(certs, i);
uint32_t ex_flags = X509_get_extension_flags(x);
/* Access the cache which we now know exists */
cache = ossl_policy_cache_set(x);
X509_up_ref(x);
(++level)->cert = x;
if (!cache->anyPolicy)
level->flags |= X509_V_FLAG_INHIBIT_ANY;
/* Determine inhibit any and inhibit map flags */
if (any_skip == 0) {
/*
* Any matching allowed only if certificate is self issued and not
* the last in the chain.
*/
if (!(ex_flags & EXFLAG_SI) || (i == 0))
level->flags |= X509_V_FLAG_INHIBIT_ANY;
} else {
if (!(ex_flags & EXFLAG_SI))
any_skip--;
if ((cache->any_skip >= 0) && (cache->any_skip < any_skip))
any_skip = cache->any_skip;
}
if (map_skip == 0)
level->flags |= X509_V_FLAG_INHIBIT_MAP;
else {
if (!(ex_flags & EXFLAG_SI))
map_skip--;
if ((cache->map_skip >= 0) && (cache->map_skip < map_skip))
map_skip = cache->map_skip;
}
}
*ptree = tree;
return ret;
bad_tree:
X509_policy_tree_free(tree);
return X509_PCY_TREE_INTERNAL;
}
/*
* Return value: 1 on success, 0 otherwise
*/
static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
- X509_POLICY_DATA *data)
+ X509_POLICY_DATA *data,
+ X509_POLICY_TREE *tree)
{
X509_POLICY_LEVEL *last = curr - 1;
int i, matched = 0;
/* Iterate through all in nodes linking matches */
for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(last->nodes, i);
if (ossl_policy_node_match(last, node, data->valid_policy)) {
- if (ossl_policy_level_add_node(curr, data, node, NULL) == NULL)
+ if (ossl_policy_level_add_node(curr, data, node, tree, 0) == NULL)
return 0;
matched = 1;
}
}
if (!matched && last->anyPolicy) {
- if (ossl_policy_level_add_node(curr, data, last->anyPolicy, NULL) == NULL)
+ if (ossl_policy_level_add_node(curr, data, last->anyPolicy, tree, 0) == NULL)
return 0;
}
return 1;
}
/*
* This corresponds to RFC3280 6.1.3(d)(1): link any data from
* CertificatePolicies onto matching parent or anyPolicy if no match.
*
* Return value: 1 on success, 0 otherwise.
*/
static int tree_link_nodes(X509_POLICY_LEVEL *curr,
- const X509_POLICY_CACHE *cache)
+ const X509_POLICY_CACHE *cache,
+ X509_POLICY_TREE *tree)
{
int i;
for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) {
X509_POLICY_DATA *data = sk_X509_POLICY_DATA_value(cache->data, i);
/* Look for matching nodes in previous level */
- if (!tree_link_matching_nodes(curr, data))
+ if (!tree_link_matching_nodes(curr, data, tree))
return 0;
}
return 1;
}
/*
* This corresponds to RFC3280 6.1.3(d)(2): Create new data for any unmatched
* policies in the parent and link to anyPolicy.
*
* Return value: 1 on success, 0 otherwise.
*/
static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
const X509_POLICY_CACHE *cache,
const ASN1_OBJECT *id,
X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
{
X509_POLICY_DATA *data;
if (id == NULL)
id = node->data->valid_policy;
/*
* Create a new node with qualifiers from anyPolicy and id from unmatched
* node.
*/
if ((data = ossl_policy_data_new(NULL, id, node_critical(node))) == NULL)
return 0;
/* Curr may not have anyPolicy */
data->qualifier_set = cache->anyPolicy->qualifier_set;
data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
- if (ossl_policy_level_add_node(curr, data, node, tree) == NULL) {
+ if (ossl_policy_level_add_node(curr, data, node, tree, 1) == NULL) {
ossl_policy_data_free(data);
return 0;
}
return 1;
}
/*
* Return value: 1 on success, 0 otherwise.
*/
static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
const X509_POLICY_CACHE *cache,
X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
{
const X509_POLICY_LEVEL *last = curr - 1;
int i;
if ((last->flags & X509_V_FLAG_INHIBIT_MAP)
|| !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) {
/* If no policy mapping: matched if one child present */
if (node->nchild)
return 1;
if (!tree_add_unmatched(curr, cache, NULL, node, tree))
return 0;
/* Add it */
} else {
/* If mapping: matched if one child per expected policy set */
STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
if (node->nchild == sk_ASN1_OBJECT_num(expset))
return 1;
/* Locate unmatched nodes */
for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) {
ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
if (ossl_policy_level_find_node(curr, node, oid))
continue;
if (!tree_add_unmatched(curr, cache, oid, node, tree))
return 0;
}
}
return 1;
}
/*
* Return value: 1 on success, 0 otherwise
*/
static int tree_link_any(X509_POLICY_LEVEL *curr,
const X509_POLICY_CACHE *cache,
X509_POLICY_TREE *tree)
{
int i;
X509_POLICY_NODE *node;
X509_POLICY_LEVEL *last = curr - 1;
for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
node = sk_X509_POLICY_NODE_value(last->nodes, i);
if (!tree_link_unmatched(curr, cache, node, tree))
return 0;
}
/* Finally add link to anyPolicy */
if (last->anyPolicy &&
ossl_policy_level_add_node(curr, cache->anyPolicy,
- last->anyPolicy, NULL) == NULL)
+ last->anyPolicy, tree, 0) == NULL)
return 0;
return 1;
}
/*-
* Prune the tree: delete any child mapped child data on the current level then
* proceed up the tree deleting any data with no children. If we ever have no
* data on a level we can halt because the tree will be empty.
*
* Return value: <= 0 error, otherwise one of:
*
* X509_PCY_TREE_VALID: valid tree
* X509_PCY_TREE_EMPTY: empty tree
*/
static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
{
STACK_OF(X509_POLICY_NODE) *nodes;
X509_POLICY_NODE *node;
int i;
nodes = curr->nodes;
if (curr->flags & X509_V_FLAG_INHIBIT_MAP) {
for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
node = sk_X509_POLICY_NODE_value(nodes, i);
/* Delete any mapped data: see RFC3280 XXXX */
if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) {
node->parent->nchild--;
OPENSSL_free(node);
(void)sk_X509_POLICY_NODE_delete(nodes, i);
}
}
}
for (;;) {
--curr;
nodes = curr->nodes;
for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
node = sk_X509_POLICY_NODE_value(nodes, i);
if (node->nchild == 0) {
node->parent->nchild--;
OPENSSL_free(node);
(void)sk_X509_POLICY_NODE_delete(nodes, i);
}
}
if (curr->anyPolicy && !curr->anyPolicy->nchild) {
if (curr->anyPolicy->parent)
curr->anyPolicy->parent->nchild--;
OPENSSL_free(curr->anyPolicy);
curr->anyPolicy = NULL;
}
if (curr == tree->levels) {
/* If we zapped anyPolicy at top then tree is empty */
if (!curr->anyPolicy)
return X509_PCY_TREE_EMPTY;
break;
}
}
return X509_PCY_TREE_VALID;
}
/*
* Return value: 1 on success, 0 otherwise.
*/
static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
X509_POLICY_NODE *pcy)
{
if (*pnodes == NULL &&
(*pnodes = ossl_policy_node_cmp_new()) == NULL)
return 0;
if (sk_X509_POLICY_NODE_find(*pnodes, pcy) >= 0)
return 1;
return sk_X509_POLICY_NODE_push(*pnodes, pcy) != 0;
}
#define TREE_CALC_FAILURE 0
#define TREE_CALC_OK_NOFREE 1
#define TREE_CALC_OK_DOFREE 2
/*-
* Calculate the authority set based on policy tree. The 'pnodes' parameter is
* used as a store for the set of policy nodes used to calculate the user set.
* If the authority set is not anyPolicy then pnodes will just point to the
* authority set. If however the authority set is anyPolicy then the set of
* valid policies (other than anyPolicy) is store in pnodes.
*
* Return value:
* TREE_CALC_FAILURE on failure,
* TREE_CALC_OK_NOFREE on success and pnodes need not be freed,
* TREE_CALC_OK_DOFREE on success and pnodes needs to be freed
*/
static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
STACK_OF(X509_POLICY_NODE) **pnodes)
{
X509_POLICY_LEVEL *curr;
X509_POLICY_NODE *node, *anyptr;
STACK_OF(X509_POLICY_NODE) **addnodes;
int i, j;
curr = tree->levels + tree->nlevel - 1;
/* If last level contains anyPolicy set is anyPolicy */
if (curr->anyPolicy) {
if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
return TREE_CALC_FAILURE;
addnodes = pnodes;
} else
/* Add policies to authority set */
addnodes = &tree->auth_policies;
curr = tree->levels;
for (i = 1; i < tree->nlevel; i++) {
/*
* If no anyPolicy node on this level it can't appear on lower
* levels so end search.
*/
if ((anyptr = curr->anyPolicy) == NULL)
break;
curr++;
for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) {
node = sk_X509_POLICY_NODE_value(curr->nodes, j);
if ((node->parent == anyptr)
&& !tree_add_auth_node(addnodes, node)) {
if (addnodes == pnodes) {
sk_X509_POLICY_NODE_free(*pnodes);
*pnodes = NULL;
}
return TREE_CALC_FAILURE;
}
}
}
if (addnodes == pnodes)
return TREE_CALC_OK_DOFREE;
*pnodes = tree->auth_policies;
return TREE_CALC_OK_NOFREE;
}
/*
* Return value: 1 on success, 0 otherwise.
*/
static int tree_calculate_user_set(X509_POLICY_TREE *tree,
STACK_OF(ASN1_OBJECT) *policy_oids,
STACK_OF(X509_POLICY_NODE) *auth_nodes)
{
int i;
X509_POLICY_NODE *node;
ASN1_OBJECT *oid;
X509_POLICY_NODE *anyPolicy;
X509_POLICY_DATA *extra;
/*
* Check if anyPolicy present in authority constrained policy set: this
* will happen if it is a leaf node.
*/
if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
return 1;
anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
oid = sk_ASN1_OBJECT_value(policy_oids, i);
if (OBJ_obj2nid(oid) == NID_any_policy) {
tree->flags |= POLICY_FLAG_ANY_POLICY;
return 1;
}
}
for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
oid = sk_ASN1_OBJECT_value(policy_oids, i);
node = ossl_policy_tree_find_sk(auth_nodes, oid);
if (!node) {
if (!anyPolicy)
continue;
/*
* Create a new node with policy ID from user set and qualifiers
* from anyPolicy.
*/
extra = ossl_policy_data_new(NULL, oid, node_critical(anyPolicy));
if (extra == NULL)
return 0;
extra->qualifier_set = anyPolicy->data->qualifier_set;
extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
| POLICY_DATA_FLAG_EXTRA_NODE;
node = ossl_policy_level_add_node(NULL, extra, anyPolicy->parent,
- tree);
+ tree, 1);
+ if (node == NULL) {
+ ossl_policy_data_free(extra);
+ return 0;
+ }
}
if (!tree->user_policies) {
tree->user_policies = sk_X509_POLICY_NODE_new_null();
- if (!tree->user_policies)
- return 1;
+ if (!tree->user_policies) {
+ exnode_free(node);
+ return 0;
+ }
}
- if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
+ if (!sk_X509_POLICY_NODE_push(tree->user_policies, node)) {
+ exnode_free(node);
return 0;
+ }
}
return 1;
}
/*-
* Return value: <= 0 error, otherwise one of:
* X509_PCY_TREE_VALID: valid tree
* X509_PCY_TREE_EMPTY: empty tree
* (see tree_prune()).
*/
static int tree_evaluate(X509_POLICY_TREE *tree)
{
int ret, i;
X509_POLICY_LEVEL *curr = tree->levels + 1;
const X509_POLICY_CACHE *cache;
for (i = 1; i < tree->nlevel; i++, curr++) {
cache = ossl_policy_cache_set(curr->cert);
- if (!tree_link_nodes(curr, cache))
+ if (!tree_link_nodes(curr, cache, tree))
return X509_PCY_TREE_INTERNAL;
if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
&& !tree_link_any(curr, cache, tree))
return X509_PCY_TREE_INTERNAL;
TREE_PRINT("before tree_prune()", tree, curr);
ret = tree_prune(tree, curr);
if (ret != X509_PCY_TREE_VALID)
return ret;
}
return X509_PCY_TREE_VALID;
}
static void exnode_free(X509_POLICY_NODE *node)
{
if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
OPENSSL_free(node);
}
void X509_policy_tree_free(X509_POLICY_TREE *tree)
{
X509_POLICY_LEVEL *curr;
int i;
if (!tree)
return;
sk_X509_POLICY_NODE_free(tree->auth_policies);
sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) {
X509_free(curr->cert);
sk_X509_POLICY_NODE_pop_free(curr->nodes, ossl_policy_node_free);
ossl_policy_node_free(curr->anyPolicy);
}
sk_X509_POLICY_DATA_pop_free(tree->extra_data, ossl_policy_data_free);
OPENSSL_free(tree->levels);
OPENSSL_free(tree);
}
/*-
* Application policy checking function.
* Return codes:
* X509_PCY_TREE_FAILURE: Failure to satisfy explicit policy
* X509_PCY_TREE_INVALID: Inconsistent or invalid extensions
* X509_PCY_TREE_INTERNAL: Internal error, most likely malloc
* X509_PCY_TREE_VALID: Success (null tree if empty or bare TA)
*/
int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
STACK_OF(X509) *certs,
STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags)
{
int init_ret;
int ret;
int calc_ret;
X509_POLICY_TREE *tree = NULL;
STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
*ptree = NULL;
*pexplicit_policy = 0;
init_ret = tree_init(&tree, certs, flags);
if (init_ret <= 0)
return init_ret;
if ((init_ret & X509_PCY_TREE_EXPLICIT) == 0) {
if (init_ret & X509_PCY_TREE_EMPTY) {
X509_policy_tree_free(tree);
return X509_PCY_TREE_VALID;
}
} else {
*pexplicit_policy = 1;
/* Tree empty and requireExplicit True: Error */
if (init_ret & X509_PCY_TREE_EMPTY)
return X509_PCY_TREE_FAILURE;
}
ret = tree_evaluate(tree);
TREE_PRINT("tree_evaluate()", tree, NULL);
if (ret <= 0)
goto error;
if (ret == X509_PCY_TREE_EMPTY) {
X509_policy_tree_free(tree);
if (init_ret & X509_PCY_TREE_EXPLICIT)
return X509_PCY_TREE_FAILURE;
return X509_PCY_TREE_VALID;
}
/* Tree is not empty: continue */
if ((calc_ret = tree_calculate_authority_set(tree, &auth_nodes)) == 0)
goto error;
ret = tree_calculate_user_set(tree, policy_oids, auth_nodes);
if (calc_ret == TREE_CALC_OK_DOFREE)
sk_X509_POLICY_NODE_free(auth_nodes);
if (!ret)
goto error;
*ptree = tree;
if (init_ret & X509_PCY_TREE_EXPLICIT) {
nodes = X509_policy_tree_get0_user_policies(tree);
if (sk_X509_POLICY_NODE_num(nodes) <= 0)
return X509_PCY_TREE_FAILURE;
}
return X509_PCY_TREE_VALID;
error:
X509_policy_tree_free(tree);
return X509_PCY_TREE_INTERNAL;
}
diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c
index f25bb41acb52..61d41117e2c0 100644
--- a/crypto/x509/x509_txt.c
+++ b/crypto/x509/x509_txt.c
@@ -1,220 +1,225 @@
/*
* 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 <time.h>
#include <errno.h>
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/evp.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/objects.h>
const char *X509_verify_cert_error_string(long n)
{
switch ((int)n) {
case X509_V_OK:
return "ok";
case X509_V_ERR_UNSPECIFIED:
return "unspecified certificate verification error";
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
return "unable to get issuer certificate";
case X509_V_ERR_UNABLE_TO_GET_CRL:
return "unable to get certificate CRL";
case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
return "unable to decrypt certificate's signature";
case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
return "unable to decrypt CRL's signature";
case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
return "unable to decode issuer public key";
case X509_V_ERR_CERT_SIGNATURE_FAILURE:
return "certificate signature failure";
case X509_V_ERR_CRL_SIGNATURE_FAILURE:
return "CRL signature failure";
case X509_V_ERR_CERT_NOT_YET_VALID:
return "certificate is not yet valid";
case X509_V_ERR_CERT_HAS_EXPIRED:
return "certificate has expired";
case X509_V_ERR_CRL_NOT_YET_VALID:
return "CRL is not yet valid";
case X509_V_ERR_CRL_HAS_EXPIRED:
return "CRL has expired";
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
return "format error in certificate's notBefore field";
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
return "format error in certificate's notAfter field";
case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
return "format error in CRL's lastUpdate field";
case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
return "format error in CRL's nextUpdate field";
case X509_V_ERR_OUT_OF_MEM:
return "out of memory";
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
return "self-signed certificate";
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
return "self-signed certificate in certificate chain";
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
return "unable to get local issuer certificate";
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
return "unable to verify the first certificate";
case X509_V_ERR_CERT_CHAIN_TOO_LONG:
return "certificate chain too long";
case X509_V_ERR_CERT_REVOKED:
return "certificate revoked";
case X509_V_ERR_NO_ISSUER_PUBLIC_KEY:
return "issuer certificate doesn't have a public key";
case X509_V_ERR_PATH_LENGTH_EXCEEDED:
return "path length constraint exceeded";
case X509_V_ERR_INVALID_PURPOSE:
return "unsuitable certificate purpose";
case X509_V_ERR_CERT_UNTRUSTED:
return "certificate not trusted";
case X509_V_ERR_CERT_REJECTED:
return "certificate rejected";
case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
return "subject issuer mismatch";
case X509_V_ERR_AKID_SKID_MISMATCH:
return "authority and subject key identifier mismatch";
case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
return "authority and issuer serial number mismatch";
case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
return "key usage does not include certificate signing";
case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
return "unable to get CRL issuer certificate";
case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
return "unhandled critical extension";
case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN:
return "key usage does not include CRL signing";
case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION:
return "unhandled critical CRL extension";
case X509_V_ERR_INVALID_NON_CA:
return "invalid non-CA certificate (has CA markings)";
case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED:
return "proxy path length constraint exceeded";
case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE:
return "key usage does not include digital signature";
case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED:
return
"proxy certificates not allowed, please set the appropriate flag";
case X509_V_ERR_INVALID_EXTENSION:
return "invalid or inconsistent certificate extension";
case X509_V_ERR_INVALID_POLICY_EXTENSION:
return "invalid or inconsistent certificate policy extension";
case X509_V_ERR_NO_EXPLICIT_POLICY:
return "no explicit policy";
case X509_V_ERR_DIFFERENT_CRL_SCOPE:
return "different CRL scope";
case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE:
return "unsupported extension feature";
case X509_V_ERR_UNNESTED_RESOURCE:
return "RFC 3779 resource not subset of parent's resources";
case X509_V_ERR_PERMITTED_VIOLATION:
return "permitted subtree violation";
case X509_V_ERR_EXCLUDED_VIOLATION:
return "excluded subtree violation";
case X509_V_ERR_SUBTREE_MINMAX:
return "name constraints minimum and maximum not supported";
case X509_V_ERR_APPLICATION_VERIFICATION:
return "application verification failure";
case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE:
return "unsupported name constraint type";
case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX:
return "unsupported or invalid name constraint syntax";
case X509_V_ERR_UNSUPPORTED_NAME_SYNTAX:
return "unsupported or invalid name syntax";
case X509_V_ERR_CRL_PATH_VALIDATION_ERROR:
return "CRL path validation error";
case X509_V_ERR_PATH_LOOP:
return "path loop";
case X509_V_ERR_SUITE_B_INVALID_VERSION:
return "Suite B: certificate version invalid";
case X509_V_ERR_SUITE_B_INVALID_ALGORITHM:
return "Suite B: invalid public key algorithm";
case X509_V_ERR_SUITE_B_INVALID_CURVE:
return "Suite B: invalid ECC curve";
case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM:
return "Suite B: invalid signature algorithm";
case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED:
return "Suite B: curve not allowed for this LOS";
case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256:
return "Suite B: cannot sign P-384 with P-256";
case X509_V_ERR_HOSTNAME_MISMATCH:
return "hostname mismatch";
case X509_V_ERR_EMAIL_MISMATCH:
return "email address mismatch";
case X509_V_ERR_IP_ADDRESS_MISMATCH:
return "IP address mismatch";
case X509_V_ERR_DANE_NO_MATCH:
return "no matching DANE TLSA records";
case X509_V_ERR_EE_KEY_TOO_SMALL:
return "EE certificate key too weak";
case X509_V_ERR_CA_KEY_TOO_SMALL:
return "CA certificate key too weak";
case X509_V_ERR_CA_MD_TOO_WEAK:
return "CA signature digest algorithm too weak";
case X509_V_ERR_INVALID_CALL:
return "invalid certificate verification context";
case X509_V_ERR_STORE_LOOKUP:
return "issuer certificate lookup error";
case X509_V_ERR_NO_VALID_SCTS:
return "Certificate Transparency required, but no valid SCTs found";
case X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION:
return "proxy subject name violation";
case X509_V_ERR_OCSP_VERIFY_NEEDED:
return "OCSP verification needed";
case X509_V_ERR_OCSP_VERIFY_FAILED:
return "OCSP verification failed";
case X509_V_ERR_OCSP_CERT_UNKNOWN:
return "OCSP unknown cert";
case X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM:
return "Cannot find certificate signature algorithm";
case X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH:
return "subject signature algorithm and issuer public key algorithm mismatch";
case X509_V_ERR_SIGNATURE_ALGORITHM_INCONSISTENCY:
- return "cert info siganature and signature algorithm mismatch";
+ return "cert info signature and signature algorithm mismatch";
case X509_V_ERR_INVALID_CA:
return "invalid CA certificate";
case X509_V_ERR_PATHLEN_INVALID_FOR_NON_CA:
return "Path length invalid for non-CA cert";
case X509_V_ERR_PATHLEN_WITHOUT_KU_KEY_CERT_SIGN:
return "Path length given without key usage keyCertSign";
case X509_V_ERR_KU_KEY_CERT_SIGN_INVALID_FOR_NON_CA:
return "Key usage keyCertSign invalid for non-CA cert";
case X509_V_ERR_ISSUER_NAME_EMPTY:
return "Issuer name empty";
case X509_V_ERR_SUBJECT_NAME_EMPTY:
return "Subject name empty";
case X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER:
return "Missing Authority Key Identifier";
case X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER:
return "Missing Subject Key Identifier";
case X509_V_ERR_EMPTY_SUBJECT_ALT_NAME:
return "Empty Subject Alternative Name extension";
case X509_V_ERR_CA_BCONS_NOT_CRITICAL:
return "Basic Constraints of CA cert not marked critical";
case X509_V_ERR_EMPTY_SUBJECT_SAN_NOT_CRITICAL:
return "Subject empty and Subject Alt Name extension not critical";
case X509_V_ERR_AUTHORITY_KEY_IDENTIFIER_CRITICAL:
return "Authority Key Identifier marked critical";
case X509_V_ERR_SUBJECT_KEY_IDENTIFIER_CRITICAL:
return "Subject Key Identifier marked critical";
case X509_V_ERR_CA_CERT_MISSING_KEY_USAGE:
return "CA cert does not include key usage extension";
case X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3:
return "Using cert extension requires at least X509v3";
case X509_V_ERR_EC_KEY_EXPLICIT_PARAMS:
return "Certificate public key has explicit ECC parameters";
+ /*
+ * Entries must be kept consistent with include/openssl/x509_vfy.h.in
+ * and with doc/man3/X509_STORE_CTX_get_error.pod
+ */
+
default:
/* Printing an error number into a static buffer is not thread-safe */
return "unknown certificate verification error";
}
}
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 9384f1da9bad..d19efeaa9919 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -1,3443 +1,3451 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 "internal/deprecated.h"
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <limits.h>
#include "crypto/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/crypto.h>
#include <openssl/buffer.h>
#include <openssl/evp.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include <openssl/core_names.h>
#include "internal/dane.h"
#include "crypto/x509.h"
#include "x509_local.h"
/* CRL score values */
#define CRL_SCORE_NOCRITICAL 0x100 /* No unhandled critical extensions */
#define CRL_SCORE_SCOPE 0x080 /* certificate is within CRL scope */
#define CRL_SCORE_TIME 0x040 /* CRL times valid */
#define CRL_SCORE_ISSUER_NAME 0x020 /* Issuer name matches certificate */
#define CRL_SCORE_VALID /* If this score or above CRL is probably valid */ \
(CRL_SCORE_NOCRITICAL | CRL_SCORE_TIME | CRL_SCORE_SCOPE)
#define CRL_SCORE_ISSUER_CERT 0x018 /* CRL issuer is certificate issuer */
#define CRL_SCORE_SAME_PATH 0x008 /* CRL issuer is on certificate path */
#define CRL_SCORE_AKID 0x004 /* CRL issuer matches CRL AKID */
#define CRL_SCORE_TIME_DELTA 0x002 /* Have a delta CRL with valid times */
static int build_chain(X509_STORE_CTX *ctx);
static int verify_chain(X509_STORE_CTX *ctx);
static int dane_verify(X509_STORE_CTX *ctx);
static int null_callback(int ok, X509_STORE_CTX *e);
static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
static int check_extensions(X509_STORE_CTX *ctx);
static int check_name_constraints(X509_STORE_CTX *ctx);
static int check_id(X509_STORE_CTX *ctx);
static int check_trust(X509_STORE_CTX *ctx, int num_untrusted);
static int check_revocation(X509_STORE_CTX *ctx);
static int check_cert(X509_STORE_CTX *ctx);
static int check_policy(X509_STORE_CTX *ctx);
static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
static int check_dane_issuer(X509_STORE_CTX *ctx, int depth);
static int check_key_level(X509_STORE_CTX *ctx, X509 *cert);
static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert);
static int check_curve(X509 *cert);
static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
unsigned int *preasons, X509_CRL *crl, X509 *x);
static int get_crl_delta(X509_STORE_CTX *ctx,
X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x);
static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl,
int *pcrl_score, X509_CRL *base,
STACK_OF(X509_CRL) *crls);
static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer,
int *pcrl_score);
static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score,
unsigned int *preasons);
static int check_crl_path(X509_STORE_CTX *ctx, X509 *x);
static int check_crl_chain(X509_STORE_CTX *ctx,
STACK_OF(X509) *cert_path,
STACK_OF(X509) *crl_path);
static int internal_verify(X509_STORE_CTX *ctx);
static int null_callback(int ok, X509_STORE_CTX *e)
{
return ok;
}
/*-
* Return 1 if given cert is considered self-signed, 0 if not, or -1 on error.
* This actually verifies self-signedness only if requested.
* It calls ossl_x509v3_cache_extensions()
* to match issuer and subject names (i.e., the cert being self-issued) and any
* present authority key identifier to match the subject key identifier, etc.
*/
int X509_self_signed(X509 *cert, int verify_signature)
{
EVP_PKEY *pkey;
if ((pkey = X509_get0_pubkey(cert)) == NULL) { /* handles cert == NULL */
ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
return -1;
}
if (!ossl_x509v3_cache_extensions(cert))
return -1;
if ((cert->ex_flags & EXFLAG_SS) == 0)
return 0;
if (!verify_signature)
return 1;
return X509_verify(cert, pkey);
}
/*
* Given a certificate, try and find an exact match in the store.
* Returns 1 on success, 0 on not found, -1 on internal error.
*/
static int lookup_cert_match(X509 **result, X509_STORE_CTX *ctx, X509 *x)
{
STACK_OF(X509) *certs;
X509 *xtmp = NULL;
int i, ret;
*result = NULL;
/* Lookup all certs with matching subject name */
ERR_set_mark();
certs = ctx->lookup_certs(ctx, X509_get_subject_name(x));
ERR_pop_to_mark();
if (certs == NULL)
return -1;
/* Look for exact match */
for (i = 0; i < sk_X509_num(certs); i++) {
xtmp = sk_X509_value(certs, i);
if (X509_cmp(xtmp, x) == 0)
break;
xtmp = NULL;
}
ret = xtmp != NULL;
if (ret) {
if (!X509_up_ref(xtmp))
ret = -1;
else
*result = xtmp;
}
sk_X509_pop_free(certs, X509_free);
return ret;
}
/*-
* Inform the verify callback of an error.
* The error code is set to |err| if |err| is not X509_V_OK, else
* |ctx->error| is left unchanged (under the assumption it is set elsewhere).
* The error depth is |depth| if >= 0, else it defaults to |ctx->error_depth|.
* The error cert is |x| if not NULL, else defaults to the chain cert at depth.
*
* Returns 0 to abort verification with an error, non-zero to continue.
*/
static int verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err)
{
if (depth < 0)
depth = ctx->error_depth;
else
ctx->error_depth = depth;
ctx->current_cert = (x != NULL) ? x : sk_X509_value(ctx->chain, depth);
if (err != X509_V_OK)
ctx->error = err;
return ctx->verify_cb(0, ctx);
}
#define CB_FAIL_IF(cond, ctx, cert, depth, err) \
if ((cond) && verify_cb_cert(ctx, cert, depth, err) == 0) \
return 0
/*-
* Inform the verify callback of an error, CRL-specific variant. Here, the
* error depth and certificate are already set, we just specify the error
* number.
*
* Returns 0 to abort verification with an error, non-zero to continue.
*/
static int verify_cb_crl(X509_STORE_CTX *ctx, int err)
{
ctx->error = err;
return ctx->verify_cb(0, ctx);
}
static int check_auth_level(X509_STORE_CTX *ctx)
{
int i;
int num = sk_X509_num(ctx->chain);
if (ctx->param->auth_level <= 0)
return 1;
for (i = 0; i < num; ++i) {
X509 *cert = sk_X509_value(ctx->chain, i);
/*
* We've already checked the security of the leaf key, so here we only
* check the security of issuer keys.
*/
CB_FAIL_IF(i > 0 && !check_key_level(ctx, cert),
ctx, cert, i, X509_V_ERR_CA_KEY_TOO_SMALL);
/*
* We also check the signature algorithm security of all certificates
* except those of the trust anchor at index num-1.
*/
CB_FAIL_IF(i < num - 1 && !check_sig_level(ctx, cert),
ctx, cert, i, X509_V_ERR_CA_MD_TOO_WEAK);
}
return 1;
}
/* Returns -1 on internal error */
static int verify_chain(X509_STORE_CTX *ctx)
{
int err;
int ok;
if ((ok = build_chain(ctx)) <= 0
|| (ok = check_extensions(ctx)) <= 0
|| (ok = check_auth_level(ctx)) <= 0
|| (ok = check_id(ctx)) <= 0
|| (ok = X509_get_pubkey_parameters(NULL, ctx->chain) ? 1 : -1) <= 0
|| (ok = ctx->check_revocation(ctx)) <= 0)
return ok;
err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
ctx->param->flags);
CB_FAIL_IF(err != X509_V_OK, ctx, NULL, ctx->error_depth, err);
/* Verify chain signatures and expiration times */
ok = ctx->verify != NULL ? ctx->verify(ctx) : internal_verify(ctx);
if (ok <= 0)
return ok;
if ((ok = check_name_constraints(ctx)) <= 0)
return ok;
#ifndef OPENSSL_NO_RFC3779
/* RFC 3779 path validation, now that CRL check has been done */
if ((ok = X509v3_asid_validate_path(ctx)) <= 0)
return ok;
if ((ok = X509v3_addr_validate_path(ctx)) <= 0)
return ok;
#endif
/* If we get this far evaluate policies */
if ((ctx->param->flags & X509_V_FLAG_POLICY_CHECK) != 0)
ok = ctx->check_policy(ctx);
return ok;
}
int X509_STORE_CTX_verify(X509_STORE_CTX *ctx)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
if (ctx->cert == NULL && sk_X509_num(ctx->untrusted) >= 1)
ctx->cert = sk_X509_value(ctx->untrusted, 0);
return X509_verify_cert(ctx);
}
int X509_verify_cert(X509_STORE_CTX *ctx)
{
int ret;
if (ctx == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
if (ctx->cert == NULL) {
ERR_raise(ERR_LIB_X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
ctx->error = X509_V_ERR_INVALID_CALL;
return -1;
}
if (ctx->chain != NULL) {
/*
* This X509_STORE_CTX has already been used to verify a cert. We
* cannot do another one.
*/
ERR_raise(ERR_LIB_X509, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
ctx->error = X509_V_ERR_INVALID_CALL;
return -1;
}
if (!ossl_x509_add_cert_new(&ctx->chain, ctx->cert, X509_ADD_FLAG_UP_REF)) {
ctx->error = X509_V_ERR_OUT_OF_MEM;
return -1;
}
ctx->num_untrusted = 1;
/* If the peer's public key is too weak, we can stop early. */
CB_FAIL_IF(!check_key_level(ctx, ctx->cert),
ctx, ctx->cert, 0, X509_V_ERR_EE_KEY_TOO_SMALL);
ret = DANETLS_ENABLED(ctx->dane) ? dane_verify(ctx) : verify_chain(ctx);
/*
* Safety-net. If we are returning an error, we must also set ctx->error,
* so that the chain is not considered verified should the error be ignored
* (e.g. TLS with SSL_VERIFY_NONE).
*/
if (ret <= 0 && ctx->error == X509_V_OK)
ctx->error = X509_V_ERR_UNSPECIFIED;
return ret;
}
static int sk_X509_contains(STACK_OF(X509) *sk, X509 *cert)
{
int i, n = sk_X509_num(sk);
for (i = 0; i < n; i++)
if (X509_cmp(sk_X509_value(sk, i), cert) == 0)
return 1;
return 0;
}
/*
* Find in given STACK_OF(X509) |sk| an issuer cert (if any) of given cert |x|.
* The issuer must not yet be in |ctx->chain|, yet allowing the exception that
* |x| is self-issued and |ctx->chain| has just one element.
* Prefer the first non-expired one, else take the most recently expired one.
*/
static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
{
int i;
X509 *issuer, *rv = NULL;
for (i = 0; i < sk_X509_num(sk); i++) {
issuer = sk_X509_value(sk, i);
if (ctx->check_issued(ctx, x, issuer)
&& (((x->ex_flags & EXFLAG_SI) != 0 && sk_X509_num(ctx->chain) == 1)
|| !sk_X509_contains(ctx->chain, issuer))) {
if (ossl_x509_check_cert_time(ctx, issuer, -1))
return issuer;
if (rv == NULL || ASN1_TIME_compare(X509_get0_notAfter(issuer),
X509_get0_notAfter(rv)) > 0)
rv = issuer;
}
}
return rv;
}
/* Check that the given certificate 'x' is issued by the certificate 'issuer' */
static int check_issued(ossl_unused X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
{
int err = ossl_x509_likely_issued(issuer, x);
if (err == X509_V_OK)
return 1;
/*
* SUBJECT_ISSUER_MISMATCH just means 'x' is clearly not issued by 'issuer'.
* Every other error code likely indicates a real error.
*/
return 0;
}
/*-
* Alternative get_issuer method: look up from a STACK_OF(X509) in other_ctx.
* Returns -1 on internal error.
*/
static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
{
*issuer = find_issuer(ctx, ctx->other_ctx, x);
if (*issuer != NULL)
return X509_up_ref(*issuer) ? 1 : -1;
return 0;
}
/*-
* Alternative lookup method: look from a STACK stored in other_ctx.
* Returns NULL on internal error (such as out of memory).
*/
static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx,
const X509_NAME *nm)
{
STACK_OF(X509) *sk = sk_X509_new_null();
X509 *x;
int i;
if (sk == NULL)
return NULL;
for (i = 0; i < sk_X509_num(ctx->other_ctx); i++) {
x = sk_X509_value(ctx->other_ctx, i);
if (X509_NAME_cmp(nm, X509_get_subject_name(x)) == 0) {
if (!X509_add_cert(sk, x, X509_ADD_FLAG_UP_REF)) {
sk_X509_pop_free(sk, X509_free);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return NULL;
}
}
}
return sk;
}
/*
* Check EE or CA certificate purpose. For trusted certificates explicit local
* auxiliary trust can be used to override EKU-restrictions.
* Sadly, returns 0 also on internal error.
*/
static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth,
int must_be_ca)
{
int tr_ok = X509_TRUST_UNTRUSTED;
/*
* For trusted certificates we want to see whether any auxiliary trust
* settings trump the purpose constraints.
*
* This is complicated by the fact that the trust ordinals in
* ctx->param->trust are entirely independent of the purpose ordinals in
* ctx->param->purpose!
*
* What connects them is their mutual initialization via calls from
* X509_STORE_CTX_set_default() into X509_VERIFY_PARAM_lookup() which sets
* related values of both param->trust and param->purpose. It is however
* typically possible to infer associated trust values from a purpose value
* via the X509_PURPOSE API.
*
* Therefore, we can only check for trust overrides when the purpose we're
* checking is the same as ctx->param->purpose and ctx->param->trust is
* also set.
*/
if (depth >= ctx->num_untrusted && purpose == ctx->param->purpose)
tr_ok = X509_check_trust(x, ctx->param->trust, X509_TRUST_NO_SS_COMPAT);
switch (tr_ok) {
case X509_TRUST_TRUSTED:
return 1;
case X509_TRUST_REJECTED:
break;
default:
switch (X509_check_purpose(x, purpose, must_be_ca > 0)) {
case 1:
return 1;
case 0:
break;
default:
if ((ctx->param->flags & X509_V_FLAG_X509_STRICT) == 0)
return 1;
}
break;
}
return verify_cb_cert(ctx, x, depth, X509_V_ERR_INVALID_PURPOSE);
}
/*
* Check extensions of a cert chain for consistency with the supplied purpose.
* Sadly, returns 0 also on internal error.
*/
static int check_extensions(X509_STORE_CTX *ctx)
{
int i, must_be_ca, plen = 0;
X509 *x;
int ret, proxy_path_length = 0;
int purpose, allow_proxy_certs, num = sk_X509_num(ctx->chain);
/*-
* must_be_ca can have 1 of 3 values:
* -1: we accept both CA and non-CA certificates, to allow direct
* use of self-signed certificates (which are marked as CA).
* 0: we only accept non-CA certificates. This is currently not
* used, but the possibility is present for future extensions.
* 1: we only accept CA certificates. This is currently used for
* all certificates in the chain except the leaf certificate.
*/
must_be_ca = -1;
/* CRL path validation */
if (ctx->parent != NULL) {
allow_proxy_certs = 0;
purpose = X509_PURPOSE_CRL_SIGN;
} else {
allow_proxy_certs =
(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS) != 0;
purpose = ctx->param->purpose;
}
for (i = 0; i < num; i++) {
x = sk_X509_value(ctx->chain, i);
CB_FAIL_IF((ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) == 0
&& (x->ex_flags & EXFLAG_CRITICAL) != 0,
ctx, x, i, X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION);
CB_FAIL_IF(!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY) != 0,
ctx, x, i, X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED);
ret = X509_check_ca(x);
switch (must_be_ca) {
case -1:
CB_FAIL_IF((ctx->param->flags & X509_V_FLAG_X509_STRICT) != 0
&& ret != 1 && ret != 0,
ctx, x, i, X509_V_ERR_INVALID_CA);
break;
case 0:
CB_FAIL_IF(ret != 0, ctx, x, i, X509_V_ERR_INVALID_NON_CA);
break;
default:
/* X509_V_FLAG_X509_STRICT is implicit for intermediate CAs */
CB_FAIL_IF(ret == 0
|| ((i + 1 < num
|| (ctx->param->flags & X509_V_FLAG_X509_STRICT) != 0)
&& ret != 1), ctx, x, i, X509_V_ERR_INVALID_CA);
break;
}
if (num > 1) {
/* Check for presence of explicit elliptic curve parameters */
ret = check_curve(x);
CB_FAIL_IF(ret < 0, ctx, x, i, X509_V_ERR_UNSPECIFIED);
CB_FAIL_IF(ret == 0, ctx, x, i, X509_V_ERR_EC_KEY_EXPLICIT_PARAMS);
}
/*
* Do the following set of checks only if strict checking is requested
* and not for self-issued (including self-signed) EE (non-CA) certs
* because RFC 5280 does not apply to them according RFC 6818 section 2.
*/
if ((ctx->param->flags & X509_V_FLAG_X509_STRICT) != 0
&& num > 1) { /*
* this should imply
* !(i == 0 && (x->ex_flags & EXFLAG_CA) == 0
* && (x->ex_flags & EXFLAG_SI) != 0)
*/
/* Check Basic Constraints according to RFC 5280 section 4.2.1.9 */
if (x->ex_pathlen != -1) {
CB_FAIL_IF((x->ex_flags & EXFLAG_CA) == 0,
ctx, x, i, X509_V_ERR_PATHLEN_INVALID_FOR_NON_CA);
CB_FAIL_IF((x->ex_kusage & KU_KEY_CERT_SIGN) == 0, ctx,
x, i, X509_V_ERR_PATHLEN_WITHOUT_KU_KEY_CERT_SIGN);
}
CB_FAIL_IF((x->ex_flags & EXFLAG_CA) != 0
&& (x->ex_flags & EXFLAG_BCONS) != 0
&& (x->ex_flags & EXFLAG_BCONS_CRITICAL) == 0,
ctx, x, i, X509_V_ERR_CA_BCONS_NOT_CRITICAL);
/* Check Key Usage according to RFC 5280 section 4.2.1.3 */
if ((x->ex_flags & EXFLAG_CA) != 0) {
CB_FAIL_IF((x->ex_flags & EXFLAG_KUSAGE) == 0,
ctx, x, i, X509_V_ERR_CA_CERT_MISSING_KEY_USAGE);
} else {
CB_FAIL_IF((x->ex_kusage & KU_KEY_CERT_SIGN) != 0, ctx, x, i,
X509_V_ERR_KU_KEY_CERT_SIGN_INVALID_FOR_NON_CA);
}
/* Check issuer is non-empty acc. to RFC 5280 section 4.1.2.4 */
CB_FAIL_IF(X509_NAME_entry_count(X509_get_issuer_name(x)) == 0,
ctx, x, i, X509_V_ERR_ISSUER_NAME_EMPTY);
/* Check subject is non-empty acc. to RFC 5280 section 4.1.2.6 */
CB_FAIL_IF(((x->ex_flags & EXFLAG_CA) != 0
|| (x->ex_kusage & KU_CRL_SIGN) != 0
|| x->altname == NULL)
&& X509_NAME_entry_count(X509_get_subject_name(x)) == 0,
ctx, x, i, X509_V_ERR_SUBJECT_NAME_EMPTY);
CB_FAIL_IF(X509_NAME_entry_count(X509_get_subject_name(x)) == 0
&& x->altname != NULL
&& (x->ex_flags & EXFLAG_SAN_CRITICAL) == 0,
ctx, x, i, X509_V_ERR_EMPTY_SUBJECT_SAN_NOT_CRITICAL);
/* Check SAN is non-empty according to RFC 5280 section 4.2.1.6 */
CB_FAIL_IF(x->altname != NULL
&& sk_GENERAL_NAME_num(x->altname) <= 0,
ctx, x, i, X509_V_ERR_EMPTY_SUBJECT_ALT_NAME);
/* Check sig alg consistency acc. to RFC 5280 section 4.1.1.2 */
CB_FAIL_IF(X509_ALGOR_cmp(&x->sig_alg, &x->cert_info.signature) != 0,
ctx, x, i, X509_V_ERR_SIGNATURE_ALGORITHM_INCONSISTENCY);
CB_FAIL_IF(x->akid != NULL
&& (x->ex_flags & EXFLAG_AKID_CRITICAL) != 0,
ctx, x, i, X509_V_ERR_AUTHORITY_KEY_IDENTIFIER_CRITICAL);
CB_FAIL_IF(x->skid != NULL
&& (x->ex_flags & EXFLAG_SKID_CRITICAL) != 0,
ctx, x, i, X509_V_ERR_SUBJECT_KEY_IDENTIFIER_CRITICAL);
if (X509_get_version(x) >= X509_VERSION_3) {
/* Check AKID presence acc. to RFC 5280 section 4.2.1.1 */
CB_FAIL_IF(i + 1 < num /*
* this means not last cert in chain,
* taken as "generated by conforming CAs"
*/
&& (x->akid == NULL || x->akid->keyid == NULL), ctx,
x, i, X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER);
/* Check SKID presence acc. to RFC 5280 section 4.2.1.2 */
CB_FAIL_IF((x->ex_flags & EXFLAG_CA) != 0 && x->skid == NULL,
ctx, x, i, X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER);
} else {
CB_FAIL_IF(sk_X509_EXTENSION_num(X509_get0_extensions(x)) > 0,
ctx, x, i, X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3);
}
}
/* check_purpose() makes the callback as needed */
if (purpose > 0 && !check_purpose(ctx, x, purpose, i, must_be_ca))
return 0;
/* Check path length */
CB_FAIL_IF(i > 1 && x->ex_pathlen != -1
&& plen > x->ex_pathlen + proxy_path_length,
ctx, x, i, X509_V_ERR_PATH_LENGTH_EXCEEDED);
/* Increment path length if not a self-issued intermediate CA */
if (i > 0 && (x->ex_flags & EXFLAG_SI) == 0)
plen++;
/*
* If this certificate is a proxy certificate, the next certificate
* must be another proxy certificate or a EE certificate. If not,
* the next certificate must be a CA certificate.
*/
if (x->ex_flags & EXFLAG_PROXY) {
/*
* RFC3820, 4.1.3 (b)(1) stipulates that if pCPathLengthConstraint
* is less than max_path_length, the former should be copied to
* the latter, and 4.1.4 (a) stipulates that max_path_length
* should be verified to be larger than zero and decrement it.
*
* Because we're checking the certs in the reverse order, we start
* with verifying that proxy_path_length isn't larger than pcPLC,
* and copy the latter to the former if it is, and finally,
* increment proxy_path_length.
*/
if (x->ex_pcpathlen != -1) {
CB_FAIL_IF(proxy_path_length > x->ex_pcpathlen,
ctx, x, i, X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED);
proxy_path_length = x->ex_pcpathlen;
}
proxy_path_length++;
must_be_ca = 0;
} else {
must_be_ca = 1;
}
}
return 1;
}
static int has_san_id(X509 *x, int gtype)
{
int i;
int ret = 0;
GENERAL_NAMES *gs = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
if (gs == NULL)
return 0;
for (i = 0; i < sk_GENERAL_NAME_num(gs); i++) {
GENERAL_NAME *g = sk_GENERAL_NAME_value(gs, i);
if (g->type == gtype) {
ret = 1;
break;
}
}
GENERAL_NAMES_free(gs);
return ret;
}
/* Returns -1 on internal error */
static int check_name_constraints(X509_STORE_CTX *ctx)
{
int i;
/* Check name constraints for all certificates */
for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--) {
X509 *x = sk_X509_value(ctx->chain, i);
int j;
/* Ignore self-issued certs unless last in chain */
if (i != 0 && (x->ex_flags & EXFLAG_SI) != 0)
continue;
/*
* Proxy certificates policy has an extra constraint, where the
* certificate subject MUST be the issuer with a single CN entry
* added.
* (RFC 3820: 3.4, 4.1.3 (a)(4))
*/
if ((x->ex_flags & EXFLAG_PROXY) != 0) {
X509_NAME *tmpsubject = X509_get_subject_name(x);
X509_NAME *tmpissuer = X509_get_issuer_name(x);
X509_NAME_ENTRY *tmpentry = NULL;
int last_nid = 0;
int err = X509_V_OK;
int last_loc = X509_NAME_entry_count(tmpsubject) - 1;
/* Check that there are at least two RDNs */
if (last_loc < 1) {
err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
goto proxy_name_done;
}
/*
* Check that there is exactly one more RDN in subject as
* there is in issuer.
*/
if (X509_NAME_entry_count(tmpsubject)
!= X509_NAME_entry_count(tmpissuer) + 1) {
err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
goto proxy_name_done;
}
/*
* Check that the last subject component isn't part of a
* multi-valued RDN
*/
if (X509_NAME_ENTRY_set(X509_NAME_get_entry(tmpsubject, last_loc))
== X509_NAME_ENTRY_set(X509_NAME_get_entry(tmpsubject,
last_loc - 1))) {
err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
goto proxy_name_done;
}
/*
* Check that the last subject RDN is a commonName, and that
* all the previous RDNs match the issuer exactly
*/
tmpsubject = X509_NAME_dup(tmpsubject);
if (tmpsubject == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return -1;
}
tmpentry = X509_NAME_delete_entry(tmpsubject, last_loc);
last_nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(tmpentry));
if (last_nid != NID_commonName
|| X509_NAME_cmp(tmpsubject, tmpissuer) != 0) {
err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
}
X509_NAME_ENTRY_free(tmpentry);
X509_NAME_free(tmpsubject);
proxy_name_done:
CB_FAIL_IF(err != X509_V_OK, ctx, x, i, err);
}
/*
* Check against constraints for all certificates higher in chain
* including trust anchor. Trust anchor not strictly speaking needed
* but if it includes constraints it is to be assumed it expects them
* to be obeyed.
*/
for (j = sk_X509_num(ctx->chain) - 1; j > i; j--) {
NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc;
if (nc) {
int rv = NAME_CONSTRAINTS_check(x, nc);
int ret = 1;
/* If EE certificate check commonName too */
if (rv == X509_V_OK && i == 0
&& (ctx->param->hostflags
& X509_CHECK_FLAG_NEVER_CHECK_SUBJECT) == 0
&& ((ctx->param->hostflags
& X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT) != 0
|| (ret = has_san_id(x, GEN_DNS)) == 0))
rv = NAME_CONSTRAINTS_check_CN(x, nc);
if (ret < 0)
return ret;
switch (rv) {
case X509_V_OK:
break;
case X509_V_ERR_OUT_OF_MEM:
return -1;
default:
CB_FAIL_IF(1, ctx, x, i, rv);
break;
}
}
}
}
return 1;
}
static int check_id_error(X509_STORE_CTX *ctx, int errcode)
{
return verify_cb_cert(ctx, ctx->cert, 0, errcode);
}
static int check_hosts(X509 *x, X509_VERIFY_PARAM *vpm)
{
int i;
int n = sk_OPENSSL_STRING_num(vpm->hosts);
char *name;
if (vpm->peername != NULL) {
OPENSSL_free(vpm->peername);
vpm->peername = NULL;
}
for (i = 0; i < n; ++i) {
name = sk_OPENSSL_STRING_value(vpm->hosts, i);
if (X509_check_host(x, name, 0, vpm->hostflags, &vpm->peername) > 0)
return 1;
}
return n == 0;
}
static int check_id(X509_STORE_CTX *ctx)
{
X509_VERIFY_PARAM *vpm = ctx->param;
X509 *x = ctx->cert;
if (vpm->hosts != NULL && check_hosts(x, vpm) <= 0) {
if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
return 0;
}
if (vpm->email != NULL
&& X509_check_email(x, vpm->email, vpm->emaillen, 0) <= 0) {
if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH))
return 0;
}
if (vpm->ip != NULL && X509_check_ip(x, vpm->ip, vpm->iplen, 0) <= 0) {
if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH))
return 0;
}
return 1;
}
/* Returns -1 on internal error */
static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
{
int i, res;
X509 *x = NULL;
X509 *mx;
SSL_DANE *dane = ctx->dane;
int num = sk_X509_num(ctx->chain);
int trust;
/*
* Check for a DANE issuer at depth 1 or greater, if it is a DANE-TA(2)
* match, we're done, otherwise we'll merely record the match depth.
*/
if (DANETLS_HAS_TA(dane) && num_untrusted > 0 && num_untrusted < num) {
trust = check_dane_issuer(ctx, num_untrusted);
if (trust != X509_TRUST_UNTRUSTED)
return trust;
}
/*
* Check trusted certificates in chain at depth num_untrusted and up.
* Note, that depths 0..num_untrusted-1 may also contain trusted
* certificates, but the caller is expected to have already checked those,
* and wants to incrementally check just any added since.
*/
for (i = num_untrusted; i < num; i++) {
x = sk_X509_value(ctx->chain, i);
trust = X509_check_trust(x, ctx->param->trust, 0);
/* If explicitly trusted (so not neutral nor rejected) return trusted */
if (trust == X509_TRUST_TRUSTED)
goto trusted;
if (trust == X509_TRUST_REJECTED)
goto rejected;
}
/*
* If we are looking at a trusted certificate, and accept partial chains,
* the chain is PKIX trusted.
*/
if (num_untrusted < num) {
if ((ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) != 0)
goto trusted;
return X509_TRUST_UNTRUSTED;
}
if (num_untrusted == num
&& (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) != 0) {
/*
* Last-resort call with no new trusted certificates, check the leaf
* for a direct trust store match.
*/
i = 0;
x = sk_X509_value(ctx->chain, i);
res = lookup_cert_match(&mx, ctx, x);
if (res < 0)
return res;
if (mx == NULL)
return X509_TRUST_UNTRUSTED;
/*
* Check explicit auxiliary trust/reject settings. If none are set,
* we'll accept X509_TRUST_UNTRUSTED when not self-signed.
*/
trust = X509_check_trust(mx, ctx->param->trust, 0);
if (trust == X509_TRUST_REJECTED) {
X509_free(mx);
goto rejected;
}
/* Replace leaf with trusted match */
(void)sk_X509_set(ctx->chain, 0, mx);
X509_free(x);
ctx->num_untrusted = 0;
goto trusted;
}
/*
* If no trusted certs in chain at all return untrusted and allow
* standard (no issuer cert) etc errors to be indicated.
*/
return X509_TRUST_UNTRUSTED;
rejected:
return verify_cb_cert(ctx, x, i, X509_V_ERR_CERT_REJECTED) == 0
? X509_TRUST_REJECTED : X509_TRUST_UNTRUSTED;
trusted:
if (!DANETLS_ENABLED(dane))
return X509_TRUST_TRUSTED;
if (dane->pdpth < 0)
dane->pdpth = num_untrusted;
/* With DANE, PKIX alone is not trusted until we have both */
if (dane->mdpth >= 0)
return X509_TRUST_TRUSTED;
return X509_TRUST_UNTRUSTED;
}
/* Sadly, returns 0 also on internal error. */
static int check_revocation(X509_STORE_CTX *ctx)
{
int i = 0, last = 0, ok = 0;
if ((ctx->param->flags & X509_V_FLAG_CRL_CHECK) == 0)
return 1;
if ((ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) != 0) {
last = sk_X509_num(ctx->chain) - 1;
} else {
/* If checking CRL paths this isn't the EE certificate */
if (ctx->parent)
return 1;
last = 0;
}
for (i = 0; i <= last; i++) {
ctx->error_depth = i;
ok = check_cert(ctx);
if (!ok)
return ok;
}
return 1;
}
/* Sadly, returns 0 also on internal error. */
static int check_cert(X509_STORE_CTX *ctx)
{
X509_CRL *crl = NULL, *dcrl = NULL;
int ok = 0;
int cnum = ctx->error_depth;
X509 *x = sk_X509_value(ctx->chain, cnum);
ctx->current_cert = x;
ctx->current_issuer = NULL;
ctx->current_crl_score = 0;
ctx->current_reasons = 0;
if ((x->ex_flags & EXFLAG_PROXY) != 0)
return 1;
while (ctx->current_reasons != CRLDP_ALL_REASONS) {
unsigned int last_reasons = ctx->current_reasons;
/* Try to retrieve relevant CRL */
if (ctx->get_crl != NULL)
ok = ctx->get_crl(ctx, &crl, x);
else
ok = get_crl_delta(ctx, &crl, &dcrl, x);
/* If error looking up CRL, nothing we can do except notify callback */
if (!ok) {
ok = verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL);
goto done;
}
ctx->current_crl = crl;
ok = ctx->check_crl(ctx, crl);
if (!ok)
goto done;
if (dcrl != NULL) {
ok = ctx->check_crl(ctx, dcrl);
if (!ok)
goto done;
ok = ctx->cert_crl(ctx, dcrl, x);
if (!ok)
goto done;
} else {
ok = 1;
}
/* Don't look in full CRL if delta reason is removefromCRL */
if (ok != 2) {
ok = ctx->cert_crl(ctx, crl, x);
if (!ok)
goto done;
}
X509_CRL_free(crl);
X509_CRL_free(dcrl);
crl = NULL;
dcrl = NULL;
/*
* If reasons not updated we won't get anywhere by another iteration,
* so exit loop.
*/
if (last_reasons == ctx->current_reasons) {
ok = verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL);
goto done;
}
}
done:
X509_CRL_free(crl);
X509_CRL_free(dcrl);
ctx->current_crl = NULL;
return ok;
}
/* Check CRL times against values in X509_STORE_CTX */
static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify)
{
time_t *ptime;
int i;
if ((ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) != 0)
ptime = &ctx->param->check_time;
else if ((ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) != 0)
return 1;
else
ptime = NULL;
if (notify)
ctx->current_crl = crl;
i = X509_cmp_time(X509_CRL_get0_lastUpdate(crl), ptime);
if (i == 0) {
if (!notify)
return 0;
if (!verify_cb_crl(ctx, X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD))
return 0;
}
if (i > 0) {
if (!notify)
return 0;
if (!verify_cb_crl(ctx, X509_V_ERR_CRL_NOT_YET_VALID))
return 0;
}
if (X509_CRL_get0_nextUpdate(crl)) {
i = X509_cmp_time(X509_CRL_get0_nextUpdate(crl), ptime);
if (i == 0) {
if (!notify)
return 0;
if (!verify_cb_crl(ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD))
return 0;
}
/* Ignore expiration of base CRL is delta is valid */
if (i < 0 && (ctx->current_crl_score & CRL_SCORE_TIME_DELTA) == 0) {
if (!notify || !verify_cb_crl(ctx, X509_V_ERR_CRL_HAS_EXPIRED))
return 0;
}
}
if (notify)
ctx->current_crl = NULL;
return 1;
}
static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl,
X509 **pissuer, int *pscore, unsigned int *preasons,
STACK_OF(X509_CRL) *crls)
{
int i, crl_score, best_score = *pscore;
unsigned int reasons, best_reasons = 0;
X509 *x = ctx->current_cert;
X509_CRL *crl, *best_crl = NULL;
X509 *crl_issuer = NULL, *best_crl_issuer = NULL;
for (i = 0; i < sk_X509_CRL_num(crls); i++) {
crl = sk_X509_CRL_value(crls, i);
reasons = *preasons;
crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x);
if (crl_score < best_score || crl_score == 0)
continue;
/* If current CRL is equivalent use it if it is newer */
if (crl_score == best_score && best_crl != NULL) {
int day, sec;
if (ASN1_TIME_diff(&day, &sec, X509_CRL_get0_lastUpdate(best_crl),
X509_CRL_get0_lastUpdate(crl)) == 0)
continue;
/*
* ASN1_TIME_diff never returns inconsistent signs for |day|
* and |sec|.
*/
if (day <= 0 && sec <= 0)
continue;
}
best_crl = crl;
best_crl_issuer = crl_issuer;
best_score = crl_score;
best_reasons = reasons;
}
if (best_crl != NULL) {
X509_CRL_free(*pcrl);
*pcrl = best_crl;
*pissuer = best_crl_issuer;
*pscore = best_score;
*preasons = best_reasons;
X509_CRL_up_ref(best_crl);
X509_CRL_free(*pdcrl);
*pdcrl = NULL;
get_delta_sk(ctx, pdcrl, pscore, best_crl, crls);
}
if (best_score >= CRL_SCORE_VALID)
return 1;
return 0;
}
/*
* Compare two CRL extensions for delta checking purposes. They should be
* both present or both absent. If both present all fields must be identical.
*/
static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid)
{
ASN1_OCTET_STRING *exta = NULL, *extb = NULL;
int i = X509_CRL_get_ext_by_NID(a, nid, -1);
if (i >= 0) {
/* Can't have multiple occurrences */
if (X509_CRL_get_ext_by_NID(a, nid, i) != -1)
return 0;
exta = X509_EXTENSION_get_data(X509_CRL_get_ext(a, i));
}
i = X509_CRL_get_ext_by_NID(b, nid, -1);
if (i >= 0) {
if (X509_CRL_get_ext_by_NID(b, nid, i) != -1)
return 0;
extb = X509_EXTENSION_get_data(X509_CRL_get_ext(b, i));
}
if (exta == NULL && extb == NULL)
return 1;
if (exta == NULL || extb == NULL)
return 0;
return ASN1_OCTET_STRING_cmp(exta, extb) == 0;
}
/* See if a base and delta are compatible */
static int check_delta_base(X509_CRL *delta, X509_CRL *base)
{
/* Delta CRL must be a delta */
if (delta->base_crl_number == NULL)
return 0;
/* Base must have a CRL number */
if (base->crl_number == NULL)
return 0;
/* Issuer names must match */
if (X509_NAME_cmp(X509_CRL_get_issuer(base),
X509_CRL_get_issuer(delta)) != 0)
return 0;
/* AKID and IDP must match */
if (!crl_extension_match(delta, base, NID_authority_key_identifier))
return 0;
if (!crl_extension_match(delta, base, NID_issuing_distribution_point))
return 0;
/* Delta CRL base number must not exceed Full CRL number. */
if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0)
return 0;
/* Delta CRL number must exceed full CRL number */
return ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0;
}
/*
* For a given base CRL find a delta... maybe extend to delta scoring or
* retrieve a chain of deltas...
*/
static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore,
X509_CRL *base, STACK_OF(X509_CRL) *crls)
{
X509_CRL *delta;
int i;
if ((ctx->param->flags & X509_V_FLAG_USE_DELTAS) == 0)
return;
if (((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST) == 0)
return;
for (i = 0; i < sk_X509_CRL_num(crls); i++) {
delta = sk_X509_CRL_value(crls, i);
if (check_delta_base(delta, base)) {
if (check_crl_time(ctx, delta, 0))
*pscore |= CRL_SCORE_TIME_DELTA;
X509_CRL_up_ref(delta);
*dcrl = delta;
return;
}
}
*dcrl = NULL;
}
/*
* For a given CRL return how suitable it is for the supplied certificate
* 'x'. The return value is a mask of several criteria. If the issuer is not
* the certificate issuer this is returned in *pissuer. The reasons mask is
* also used to determine if the CRL is suitable: if no new reasons the CRL
* is rejected, otherwise reasons is updated.
*/
static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
unsigned int *preasons, X509_CRL *crl, X509 *x)
{
int crl_score = 0;
unsigned int tmp_reasons = *preasons, crl_reasons;
/* First see if we can reject CRL straight away */
/* Invalid IDP cannot be processed */
if ((crl->idp_flags & IDP_INVALID) != 0)
return 0;
/* Reason codes or indirect CRLs need extended CRL support */
if ((ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT) == 0) {
if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS))
return 0;
} else if ((crl->idp_flags & IDP_REASONS) != 0) {
/* If no new reasons reject */
if ((crl->idp_reasons & ~tmp_reasons) == 0)
return 0;
}
/* Don't process deltas at this stage */
else if (crl->base_crl_number != NULL)
return 0;
/* If issuer name doesn't match certificate need indirect CRL */
if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl)) != 0) {
if ((crl->idp_flags & IDP_INDIRECT) == 0)
return 0;
} else {
crl_score |= CRL_SCORE_ISSUER_NAME;
}
if ((crl->flags & EXFLAG_CRITICAL) == 0)
crl_score |= CRL_SCORE_NOCRITICAL;
/* Check expiration */
if (check_crl_time(ctx, crl, 0))
crl_score |= CRL_SCORE_TIME;
/* Check authority key ID and locate certificate issuer */
crl_akid_check(ctx, crl, pissuer, &crl_score);
/* If we can't locate certificate issuer at this point forget it */
if ((crl_score & CRL_SCORE_AKID) == 0)
return 0;
/* Check cert for matching CRL distribution points */
if (crl_crldp_check(x, crl, crl_score, &crl_reasons)) {
/* If no new reasons reject */
if ((crl_reasons & ~tmp_reasons) == 0)
return 0;
tmp_reasons |= crl_reasons;
crl_score |= CRL_SCORE_SCOPE;
}
*preasons = tmp_reasons;
return crl_score;
}
static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
X509 **pissuer, int *pcrl_score)
{
X509 *crl_issuer = NULL;
const X509_NAME *cnm = X509_CRL_get_issuer(crl);
int cidx = ctx->error_depth;
int i;
if (cidx != sk_X509_num(ctx->chain) - 1)
cidx++;
crl_issuer = sk_X509_value(ctx->chain, cidx);
if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
if (*pcrl_score & CRL_SCORE_ISSUER_NAME) {
*pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_ISSUER_CERT;
*pissuer = crl_issuer;
return;
}
}
for (cidx++; cidx < sk_X509_num(ctx->chain); cidx++) {
crl_issuer = sk_X509_value(ctx->chain, cidx);
if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
continue;
if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
*pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_SAME_PATH;
*pissuer = crl_issuer;
return;
}
}
/* Anything else needs extended CRL support */
if ((ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT) == 0)
return;
/*
* Otherwise the CRL issuer is not on the path. Look for it in the set of
* untrusted certificates.
*/
for (i = 0; i < sk_X509_num(ctx->untrusted); i++) {
crl_issuer = sk_X509_value(ctx->untrusted, i);
if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm) != 0)
continue;
if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
*pissuer = crl_issuer;
*pcrl_score |= CRL_SCORE_AKID;
return;
}
}
}
/*
* Check the path of a CRL issuer certificate. This creates a new
* X509_STORE_CTX and populates it with most of the parameters from the
* parent. This could be optimised somewhat since a lot of path checking will
* be duplicated by the parent, but this will rarely be used in practice.
*/
static int check_crl_path(X509_STORE_CTX *ctx, X509 *x)
{
X509_STORE_CTX crl_ctx = {0};
int ret;
/* Don't allow recursive CRL path validation */
if (ctx->parent != NULL)
return 0;
if (!X509_STORE_CTX_init(&crl_ctx, ctx->store, x, ctx->untrusted))
return -1;
crl_ctx.crls = ctx->crls;
/* Copy verify params across */
X509_STORE_CTX_set0_param(&crl_ctx, ctx->param);
crl_ctx.parent = ctx;
crl_ctx.verify_cb = ctx->verify_cb;
/* Verify CRL issuer */
ret = X509_verify_cert(&crl_ctx);
if (ret <= 0)
goto err;
/* Check chain is acceptable */
ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain);
err:
X509_STORE_CTX_cleanup(&crl_ctx);
return ret;
}
/*
* RFC3280 says nothing about the relationship between CRL path and
* certificate path, which could lead to situations where a certificate could
* be revoked or validated by a CA not authorized to do so. RFC5280 is more
* strict and states that the two paths must end in the same trust anchor,
* though some discussions remain... until this is resolved we use the
* RFC5280 version
*/
static int check_crl_chain(X509_STORE_CTX *ctx,
STACK_OF(X509) *cert_path,
STACK_OF(X509) *crl_path)
{
X509 *cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1);
X509 *crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1);
return X509_cmp(cert_ta, crl_ta) == 0;
}
/*-
* Check for match between two dist point names: three separate cases.
* 1. Both are relative names and compare X509_NAME types.
* 2. One full, one relative. Compare X509_NAME to GENERAL_NAMES.
* 3. Both are full names and compare two GENERAL_NAMES.
* 4. One is NULL: automatic match.
*/
static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b)
{
X509_NAME *nm = NULL;
GENERAL_NAMES *gens = NULL;
GENERAL_NAME *gena, *genb;
int i, j;
if (a == NULL || b == NULL)
return 1;
if (a->type == 1) {
if (a->dpname == NULL)
return 0;
/* Case 1: two X509_NAME */
if (b->type == 1) {
if (b->dpname == NULL)
return 0;
return X509_NAME_cmp(a->dpname, b->dpname) == 0;
}
/* Case 2: set name and GENERAL_NAMES appropriately */
nm = a->dpname;
gens = b->name.fullname;
} else if (b->type == 1) {
if (b->dpname == NULL)
return 0;
/* Case 2: set name and GENERAL_NAMES appropriately */
gens = a->name.fullname;
nm = b->dpname;
}
/* Handle case 2 with one GENERAL_NAMES and one X509_NAME */
if (nm != NULL) {
for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
gena = sk_GENERAL_NAME_value(gens, i);
if (gena->type != GEN_DIRNAME)
continue;
if (X509_NAME_cmp(nm, gena->d.directoryName) == 0)
return 1;
}
return 0;
}
/* Else case 3: two GENERAL_NAMES */
for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++) {
gena = sk_GENERAL_NAME_value(a->name.fullname, i);
for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++) {
genb = sk_GENERAL_NAME_value(b->name.fullname, j);
if (GENERAL_NAME_cmp(gena, genb) == 0)
return 1;
}
}
return 0;
}
static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score)
{
int i;
const X509_NAME *nm = X509_CRL_get_issuer(crl);
/* If no CRLissuer return is successful iff don't need a match */
if (dp->CRLissuer == NULL)
return (crl_score & CRL_SCORE_ISSUER_NAME) != 0;
for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) {
GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
if (gen->type != GEN_DIRNAME)
continue;
if (X509_NAME_cmp(gen->d.directoryName, nm) == 0)
return 1;
}
return 0;
}
/* Check CRLDP and IDP */
static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score,
unsigned int *preasons)
{
int i;
if ((crl->idp_flags & IDP_ONLYATTR) != 0)
return 0;
if ((x->ex_flags & EXFLAG_CA) != 0) {
if ((crl->idp_flags & IDP_ONLYUSER) != 0)
return 0;
} else {
if ((crl->idp_flags & IDP_ONLYCA) != 0)
return 0;
}
*preasons = crl->idp_reasons;
for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) {
DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i);
if (crldp_check_crlissuer(dp, crl, crl_score)) {
if (crl->idp == NULL
|| idp_check_dp(dp->distpoint, crl->idp->distpoint)) {
*preasons &= dp->dp_reasons;
return 1;
}
}
}
return (crl->idp == NULL || crl->idp->distpoint == NULL)
&& (crl_score & CRL_SCORE_ISSUER_NAME) != 0;
}
/*
* Retrieve CRL corresponding to current certificate. If deltas enabled try
* to find a delta CRL too
*/
static int get_crl_delta(X509_STORE_CTX *ctx,
X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x)
{
int ok;
X509 *issuer = NULL;
int crl_score = 0;
unsigned int reasons;
X509_CRL *crl = NULL, *dcrl = NULL;
STACK_OF(X509_CRL) *skcrl;
const X509_NAME *nm = X509_get_issuer_name(x);
reasons = ctx->current_reasons;
ok = get_crl_sk(ctx, &crl, &dcrl,
&issuer, &crl_score, &reasons, ctx->crls);
if (ok)
goto done;
/* Lookup CRLs from store */
skcrl = ctx->lookup_crls(ctx, nm);
/* If no CRLs found and a near match from get_crl_sk use that */
if (skcrl == NULL && crl != NULL)
goto done;
get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl);
sk_X509_CRL_pop_free(skcrl, X509_CRL_free);
done:
/* If we got any kind of CRL use it and return success */
if (crl != NULL) {
ctx->current_issuer = issuer;
ctx->current_crl_score = crl_score;
ctx->current_reasons = reasons;
*pcrl = crl;
*pdcrl = dcrl;
return 1;
}
return 0;
}
/* Check CRL validity */
static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
{
X509 *issuer = NULL;
EVP_PKEY *ikey = NULL;
int cnum = ctx->error_depth;
int chnum = sk_X509_num(ctx->chain) - 1;
/* If we have an alternative CRL issuer cert use that */
if (ctx->current_issuer != NULL) {
issuer = ctx->current_issuer;
/*
* Else find CRL issuer: if not last certificate then issuer is next
* certificate in chain.
*/
} else if (cnum < chnum) {
issuer = sk_X509_value(ctx->chain, cnum + 1);
} else {
issuer = sk_X509_value(ctx->chain, chnum);
/* If not self-issued, can't check signature */
if (!ctx->check_issued(ctx, issuer, issuer) &&
!verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER))
return 0;
}
if (issuer == NULL)
return 1;
/*
* Skip most tests for deltas because they have already been done
*/
if (crl->base_crl_number == NULL) {
/* Check for cRLSign bit if keyUsage present */
if ((issuer->ex_flags & EXFLAG_KUSAGE) != 0 &&
(issuer->ex_kusage & KU_CRL_SIGN) == 0 &&
!verify_cb_crl(ctx, X509_V_ERR_KEYUSAGE_NO_CRL_SIGN))
return 0;
if ((ctx->current_crl_score & CRL_SCORE_SCOPE) == 0 &&
!verify_cb_crl(ctx, X509_V_ERR_DIFFERENT_CRL_SCOPE))
return 0;
if ((ctx->current_crl_score & CRL_SCORE_SAME_PATH) == 0 &&
check_crl_path(ctx, ctx->current_issuer) <= 0 &&
!verify_cb_crl(ctx, X509_V_ERR_CRL_PATH_VALIDATION_ERROR))
return 0;
if ((crl->idp_flags & IDP_INVALID) != 0 &&
!verify_cb_crl(ctx, X509_V_ERR_INVALID_EXTENSION))
return 0;
}
if ((ctx->current_crl_score & CRL_SCORE_TIME) == 0 &&
!check_crl_time(ctx, crl, 1))
return 0;
/* Attempt to get issuer certificate public key */
ikey = X509_get0_pubkey(issuer);
if (ikey == NULL &&
!verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY))
return 0;
if (ikey != NULL) {
int rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags);
if (rv != X509_V_OK && !verify_cb_crl(ctx, rv))
return 0;
/* Verify CRL signature */
if (X509_CRL_verify(crl, ikey) <= 0 &&
!verify_cb_crl(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE))
return 0;
}
return 1;
}
/* Check certificate against CRL */
static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
{
X509_REVOKED *rev;
/*
* The rules changed for this... previously if a CRL contained unhandled
* critical extensions it could still be used to indicate a certificate
* was revoked. This has since been changed since critical extensions can
* change the meaning of CRL entries.
*/
if ((ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) == 0
&& (crl->flags & EXFLAG_CRITICAL) != 0 &&
!verify_cb_crl(ctx, X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION))
return 0;
/*
* Look for serial number of certificate in CRL. If found, make sure
* reason is not removeFromCRL.
*/
if (X509_CRL_get0_by_cert(crl, &rev, x)) {
if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
return 2;
if (!verify_cb_crl(ctx, X509_V_ERR_CERT_REVOKED))
return 0;
}
return 1;
}
static int check_policy(X509_STORE_CTX *ctx)
{
int ret;
if (ctx->parent)
return 1;
/*
* With DANE, the trust anchor might be a bare public key, not a
* certificate! In that case our chain does not have the trust anchor
* certificate as a top-most element. This comports well with RFC5280
* chain verification, since there too, the trust anchor is not part of the
* chain to be verified. In particular, X509_policy_check() does not look
* at the TA cert, but assumes that it is present as the top-most chain
* element. We therefore temporarily push a NULL cert onto the chain if it
* was verified via a bare public key, and pop it off right after the
* X509_policy_check() call.
*/
if (ctx->bare_ta_signed && !sk_X509_push(ctx->chain, NULL))
goto memerr;
ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
ctx->param->policies, ctx->param->flags);
if (ctx->bare_ta_signed)
(void)sk_X509_pop(ctx->chain);
if (ret == X509_PCY_TREE_INTERNAL)
goto memerr;
/* Invalid or inconsistent extensions */
if (ret == X509_PCY_TREE_INVALID) {
- int i;
+ int i, cbcalled = 0;
/* Locate certificates with bad extensions and notify callback. */
- for (i = 1; i < sk_X509_num(ctx->chain); i++) {
+ for (i = 0; i < sk_X509_num(ctx->chain); i++) {
X509 *x = sk_X509_value(ctx->chain, i);
+ if ((x->ex_flags & EXFLAG_INVALID_POLICY) != 0)
+ cbcalled = 1;
CB_FAIL_IF((x->ex_flags & EXFLAG_INVALID_POLICY) != 0,
ctx, x, i, X509_V_ERR_INVALID_POLICY_EXTENSION);
}
+ if (!cbcalled) {
+ /* Should not be able to get here */
+ ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ /* The callback ignored the error so we return success */
return 1;
}
if (ret == X509_PCY_TREE_FAILURE) {
ctx->current_cert = NULL;
ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY;
return ctx->verify_cb(0, ctx);
}
if (ret != X509_PCY_TREE_VALID) {
ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
return 0;
}
if ((ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) != 0) {
ctx->current_cert = NULL;
/*
* Verification errors need to be "sticky", a callback may have allowed
* an SSL handshake to continue despite an error, and we must then
* remain in an error state. Therefore, we MUST NOT clear earlier
* verification errors by setting the error to X509_V_OK.
*/
if (!ctx->verify_cb(2, ctx))
return 0;
}
return 1;
memerr:
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return -1;
}
/*-
* Check certificate validity times.
* If depth >= 0, invoke verification callbacks on error, otherwise just return
* the validation status.
*
* Return 1 on success, 0 otherwise.
*/
int ossl_x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth)
{
time_t *ptime;
int i;
if ((ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) != 0)
ptime = &ctx->param->check_time;
else if ((ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) != 0)
return 1;
else
ptime = NULL;
i = X509_cmp_time(X509_get0_notBefore(x), ptime);
if (i >= 0 && depth < 0)
return 0;
CB_FAIL_IF(i == 0, ctx, x, depth, X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD);
CB_FAIL_IF(i > 0, ctx, x, depth, X509_V_ERR_CERT_NOT_YET_VALID);
i = X509_cmp_time(X509_get0_notAfter(x), ptime);
if (i <= 0 && depth < 0)
return 0;
CB_FAIL_IF(i == 0, ctx, x, depth, X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD);
CB_FAIL_IF(i < 0, ctx, x, depth, X509_V_ERR_CERT_HAS_EXPIRED);
return 1;
}
/*
* Verify the issuer signatures and cert times of ctx->chain.
* Sadly, returns 0 also on internal error.
*/
static int internal_verify(X509_STORE_CTX *ctx)
{
int n = sk_X509_num(ctx->chain) - 1;
X509 *xi = sk_X509_value(ctx->chain, n);
X509 *xs = xi;
ctx->error_depth = n;
if (ctx->bare_ta_signed) {
/*
* With DANE-verified bare public key TA signatures,
* on the top certificate we check only the timestamps.
* We report the issuer as NULL because all we have is a bare key.
*/
xi = NULL;
} else if (ossl_x509_likely_issued(xi, xi) != X509_V_OK
/* exceptional case: last cert in the chain is not self-issued */
&& ((ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) == 0)) {
if (n > 0) {
n--;
ctx->error_depth = n;
xs = sk_X509_value(ctx->chain, n);
} else {
CB_FAIL_IF(1, ctx, xi, 0,
X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE);
}
/*
* The below code will certainly not do a
* self-signature check on xi because it is not self-issued.
*/
}
/*
* Do not clear error (by ctx->error = X509_V_OK), it must be "sticky",
* only the user's callback is allowed to reset errors (at its own peril).
*/
while (n >= 0) {
/*-
* For each iteration of this loop:
* n is the subject depth
* xs is the subject cert, for which the signature is to be checked
* xi is NULL for DANE-verified bare public key TA signatures
* else the supposed issuer cert containing the public key to use
* Initially xs == xi if the last cert in the chain is self-issued.
*/
/*
* Do signature check for self-signed certificates only if explicitly
* asked for because it does not add any security and just wastes time.
*/
if (xi != NULL
&& (xs != xi
|| ((ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE) != 0
&& (xi->ex_flags & EXFLAG_SS) != 0))) {
EVP_PKEY *pkey;
/*
* If the issuer's public key is not available or its key usage
* does not support issuing the subject cert, report the issuer
* cert and its depth (rather than n, the depth of the subject).
*/
int issuer_depth = n + (xs == xi ? 0 : 1);
/*
* According to https://tools.ietf.org/html/rfc5280#section-6.1.4
* step (n) we must check any given key usage extension in a CA cert
* when preparing the verification of a certificate issued by it.
* According to https://tools.ietf.org/html/rfc5280#section-4.2.1.3
* we must not verify a certificate signature if the key usage of
* the CA certificate that issued the certificate prohibits signing.
* In case the 'issuing' certificate is the last in the chain and is
* not a CA certificate but a 'self-issued' end-entity cert (i.e.,
* xs == xi && !(xi->ex_flags & EXFLAG_CA)) RFC 5280 does not apply
* (see https://tools.ietf.org/html/rfc6818#section-2) and thus
* we are free to ignore any key usage restrictions on such certs.
*/
int ret = xs == xi && (xi->ex_flags & EXFLAG_CA) == 0
? X509_V_OK : ossl_x509_signing_allowed(xi, xs);
CB_FAIL_IF(ret != X509_V_OK, ctx, xi, issuer_depth, ret);
if ((pkey = X509_get0_pubkey(xi)) == NULL) {
CB_FAIL_IF(1, ctx, xi, issuer_depth,
X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY);
} else {
CB_FAIL_IF(X509_verify(xs, pkey) <= 0,
ctx, xs, n, X509_V_ERR_CERT_SIGNATURE_FAILURE);
}
}
/* In addition to RFC 5280 requirements do also for trust anchor cert */
/* Calls verify callback as needed */
if (!ossl_x509_check_cert_time(ctx, xs, n))
return 0;
/*
* Signal success at this depth. However, the previous error (if any)
* is retained.
*/
ctx->current_issuer = xi;
ctx->current_cert = xs;
ctx->error_depth = n;
if (!ctx->verify_cb(1, ctx))
return 0;
if (--n >= 0) {
xi = xs;
xs = sk_X509_value(ctx->chain, n);
}
}
return 1;
}
int X509_cmp_current_time(const ASN1_TIME *ctm)
{
return X509_cmp_time(ctm, NULL);
}
int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
{
static const size_t utctime_length = sizeof("YYMMDDHHMMSSZ") - 1;
static const size_t generalizedtime_length = sizeof("YYYYMMDDHHMMSSZ") - 1;
ASN1_TIME *asn1_cmp_time = NULL;
int i, day, sec, ret = 0;
#ifdef CHARSET_EBCDIC
const char upper_z = 0x5A;
#else
const char upper_z = 'Z';
#endif
/*-
* Note that ASN.1 allows much more slack in the time format than RFC5280.
* In RFC5280, the representation is fixed:
* UTCTime: YYMMDDHHMMSSZ
* GeneralizedTime: YYYYMMDDHHMMSSZ
*
* We do NOT currently enforce the following RFC 5280 requirement:
* "CAs conforming to this profile MUST always encode certificate
* validity dates through the year 2049 as UTCTime; certificate validity
* dates in 2050 or later MUST be encoded as GeneralizedTime."
*/
switch (ctm->type) {
case V_ASN1_UTCTIME:
if (ctm->length != (int)(utctime_length))
return 0;
break;
case V_ASN1_GENERALIZEDTIME:
if (ctm->length != (int)(generalizedtime_length))
return 0;
break;
default:
return 0;
}
/**
* Verify the format: the ASN.1 functions we use below allow a more
* flexible format than what's mandated by RFC 5280.
* Digit and date ranges will be verified in the conversion methods.
*/
for (i = 0; i < ctm->length - 1; i++) {
if (!ossl_ascii_isdigit(ctm->data[i]))
return 0;
}
if (ctm->data[ctm->length - 1] != upper_z)
return 0;
/*
* There is ASN1_UTCTIME_cmp_time_t but no
* ASN1_GENERALIZEDTIME_cmp_time_t or ASN1_TIME_cmp_time_t,
* so we go through ASN.1
*/
asn1_cmp_time = X509_time_adj(NULL, 0, cmp_time);
if (asn1_cmp_time == NULL)
goto err;
if (ASN1_TIME_diff(&day, &sec, ctm, asn1_cmp_time) == 0)
goto err;
/*
* X509_cmp_time comparison is <=.
* The return value 0 is reserved for errors.
*/
ret = (day >= 0 && sec >= 0) ? -1 : 1;
err:
ASN1_TIME_free(asn1_cmp_time);
return ret;
}
/*
* Return 0 if time should not be checked or reference time is in range,
* or else 1 if it is past the end, or -1 if it is before the start
*/
int X509_cmp_timeframe(const X509_VERIFY_PARAM *vpm,
const ASN1_TIME *start, const ASN1_TIME *end)
{
time_t ref_time;
time_t *time = NULL;
unsigned long flags = vpm == NULL ? 0 : X509_VERIFY_PARAM_get_flags(vpm);
if ((flags & X509_V_FLAG_USE_CHECK_TIME) != 0) {
ref_time = X509_VERIFY_PARAM_get_time(vpm);
time = &ref_time;
} else if ((flags & X509_V_FLAG_NO_CHECK_TIME) != 0) {
return 0; /* this means ok */
} /* else reference time is the current time */
if (end != NULL && X509_cmp_time(end, time) < 0)
return 1;
if (start != NULL && X509_cmp_time(start, time) > 0)
return -1;
return 0;
}
ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
{
return X509_time_adj(s, adj, NULL);
}
ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm)
{
return X509_time_adj_ex(s, 0, offset_sec, in_tm);
}
ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
int offset_day, long offset_sec, time_t *in_tm)
{
time_t t;
if (in_tm)
t = *in_tm;
else
time(&t);
if (s != NULL && (s->flags & ASN1_STRING_FLAG_MSTRING) == 0) {
if (s->type == V_ASN1_UTCTIME)
return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
if (s->type == V_ASN1_GENERALIZEDTIME)
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
}
return ASN1_TIME_adj(s, t, offset_day, offset_sec);
}
/* Copy any missing public key parameters up the chain towards pkey */
int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
{
EVP_PKEY *ktmp = NULL, *ktmp2;
int i, j;
if (pkey != NULL && !EVP_PKEY_missing_parameters(pkey))
return 1;
for (i = 0; i < sk_X509_num(chain); i++) {
ktmp = X509_get0_pubkey(sk_X509_value(chain, i));
if (ktmp == NULL) {
ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
return 0;
}
if (!EVP_PKEY_missing_parameters(ktmp))
break;
ktmp = NULL;
}
if (ktmp == NULL) {
ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN);
return 0;
}
/* first, populate the other certs */
for (j = i - 1; j >= 0; j--) {
ktmp2 = X509_get0_pubkey(sk_X509_value(chain, j));
if (!EVP_PKEY_copy_parameters(ktmp2, ktmp))
return 0;
}
if (pkey != NULL)
return EVP_PKEY_copy_parameters(pkey, ktmp);
return 1;
}
/*
* Make a delta CRL as the difference between two full CRLs.
* Sadly, returns NULL also on internal error.
*/
X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
EVP_PKEY *skey, const EVP_MD *md, unsigned int flags)
{
X509_CRL *crl = NULL;
int i;
STACK_OF(X509_REVOKED) *revs = NULL;
/* CRLs can't be delta already */
if (base->base_crl_number != NULL || newer->base_crl_number != NULL) {
ERR_raise(ERR_LIB_X509, X509_R_CRL_ALREADY_DELTA);
return NULL;
}
/* Base and new CRL must have a CRL number */
if (base->crl_number == NULL || newer->crl_number == NULL) {
ERR_raise(ERR_LIB_X509, X509_R_NO_CRL_NUMBER);
return NULL;
}
/* Issuer names must match */
if (X509_NAME_cmp(X509_CRL_get_issuer(base),
X509_CRL_get_issuer(newer)) != 0) {
ERR_raise(ERR_LIB_X509, X509_R_ISSUER_MISMATCH);
return NULL;
}
/* AKID and IDP must match */
if (!crl_extension_match(base, newer, NID_authority_key_identifier)) {
ERR_raise(ERR_LIB_X509, X509_R_AKID_MISMATCH);
return NULL;
}
if (!crl_extension_match(base, newer, NID_issuing_distribution_point)) {
ERR_raise(ERR_LIB_X509, X509_R_IDP_MISMATCH);
return NULL;
}
/* Newer CRL number must exceed full CRL number */
if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0) {
ERR_raise(ERR_LIB_X509, X509_R_NEWER_CRL_NOT_NEWER);
return NULL;
}
/* CRLs must verify */
if (skey != NULL && (X509_CRL_verify(base, skey) <= 0 ||
X509_CRL_verify(newer, skey) <= 0)) {
ERR_raise(ERR_LIB_X509, X509_R_CRL_VERIFY_FAILURE);
return NULL;
}
/* Create new CRL */
crl = X509_CRL_new_ex(base->libctx, base->propq);
if (crl == NULL || !X509_CRL_set_version(crl, X509_CRL_VERSION_2))
goto memerr;
/* Set issuer name */
if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer)))
goto memerr;
if (!X509_CRL_set1_lastUpdate(crl, X509_CRL_get0_lastUpdate(newer)))
goto memerr;
if (!X509_CRL_set1_nextUpdate(crl, X509_CRL_get0_nextUpdate(newer)))
goto memerr;
/* Set base CRL number: must be critical */
if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0))
goto memerr;
/*
* Copy extensions across from newest CRL to delta: this will set CRL
* number to correct value too.
*/
for (i = 0; i < X509_CRL_get_ext_count(newer); i++) {
X509_EXTENSION *ext = X509_CRL_get_ext(newer, i);
if (!X509_CRL_add_ext(crl, ext, -1))
goto memerr;
}
/* Go through revoked entries, copying as needed */
revs = X509_CRL_get_REVOKED(newer);
for (i = 0; i < sk_X509_REVOKED_num(revs); i++) {
X509_REVOKED *rvn, *rvtmp;
rvn = sk_X509_REVOKED_value(revs, i);
/*
* Add only if not also in base.
* Need something cleverer here for some more complex CRLs covering
* multiple CAs.
*/
if (!X509_CRL_get0_by_serial(base, &rvtmp, &rvn->serialNumber)) {
rvtmp = X509_REVOKED_dup(rvn);
if (rvtmp == NULL)
goto memerr;
if (!X509_CRL_add0_revoked(crl, rvtmp)) {
X509_REVOKED_free(rvtmp);
goto memerr;
}
}
}
if (skey != NULL && md != NULL && !X509_CRL_sign(crl, skey, md))
goto memerr;
return crl;
memerr:
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
X509_CRL_free(crl);
return NULL;
}
int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
{
return CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
}
void *X509_STORE_CTX_get_ex_data(const X509_STORE_CTX *ctx, int idx)
{
return CRYPTO_get_ex_data(&ctx->ex_data, idx);
}
int X509_STORE_CTX_get_error(const X509_STORE_CTX *ctx)
{
return ctx->error;
}
void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
{
ctx->error = err;
}
int X509_STORE_CTX_get_error_depth(const X509_STORE_CTX *ctx)
{
return ctx->error_depth;
}
void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth)
{
ctx->error_depth = depth;
}
X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx)
{
return ctx->current_cert;
}
void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x)
{
ctx->current_cert = x;
}
STACK_OF(X509) *X509_STORE_CTX_get0_chain(const X509_STORE_CTX *ctx)
{
return ctx->chain;
}
STACK_OF(X509) *X509_STORE_CTX_get1_chain(const X509_STORE_CTX *ctx)
{
if (ctx->chain == NULL)
return NULL;
return X509_chain_up_ref(ctx->chain);
}
X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx)
{
return ctx->current_issuer;
}
X509_CRL *X509_STORE_CTX_get0_current_crl(const X509_STORE_CTX *ctx)
{
return ctx->current_crl;
}
X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(const X509_STORE_CTX *ctx)
{
return ctx->parent;
}
void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
{
ctx->cert = x;
}
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
{
ctx->crls = sk;
}
int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
{
/*
* XXX: Why isn't this function always used to set the associated trust?
* Should there even be a VPM->trust field at all? Or should the trust
* always be inferred from the purpose by X509_STORE_CTX_init().
*/
return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
}
int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
{
/*
* XXX: See above, this function would only be needed when the default
* trust for the purpose needs an override in a corner case.
*/
return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
}
/*
* This function is used to set the X509_STORE_CTX purpose and trust values.
* This is intended to be used when another structure has its own trust and
* purpose values which (if set) will be inherited by the ctx. If they aren't
* set then we will usually have a default purpose in mind which should then
* be used to set the trust value. An example of this is SSL use: an SSL
* structure will have its own purpose and trust settings which the
* application can set: if they aren't set then we use the default of SSL
* client/server.
*/
int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
int purpose, int trust)
{
int idx;
/* If purpose not set use default */
if (purpose == 0)
purpose = def_purpose;
/*
* If purpose is set but we don't have a default then set the default to
* the current purpose
*/
else if (def_purpose == 0)
def_purpose = purpose;
/* If we have a purpose then check it is valid */
if (purpose != 0) {
X509_PURPOSE *ptmp;
idx = X509_PURPOSE_get_by_id(purpose);
if (idx == -1) {
ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_PURPOSE_ID);
return 0;
}
ptmp = X509_PURPOSE_get0(idx);
if (ptmp->trust == X509_TRUST_DEFAULT) {
idx = X509_PURPOSE_get_by_id(def_purpose);
if (idx == -1) {
ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_PURPOSE_ID);
return 0;
}
ptmp = X509_PURPOSE_get0(idx);
}
/* If trust not set then get from purpose default */
if (trust == 0)
trust = ptmp->trust;
}
if (trust != 0) {
idx = X509_TRUST_get_by_id(trust);
if (idx == -1) {
ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_TRUST_ID);
return 0;
}
}
if (ctx->param->purpose == 0 && purpose != 0)
ctx->param->purpose = purpose;
if (ctx->param->trust == 0 && trust != 0)
ctx->param->trust = trust;
return 1;
}
X509_STORE_CTX *X509_STORE_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
{
X509_STORE_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
ctx->libctx = libctx;
if (propq != NULL) {
ctx->propq = OPENSSL_strdup(propq);
if (ctx->propq == NULL) {
OPENSSL_free(ctx);
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
}
return ctx;
}
X509_STORE_CTX *X509_STORE_CTX_new(void)
{
return X509_STORE_CTX_new_ex(NULL, NULL);
}
void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
{
if (ctx == NULL)
return;
X509_STORE_CTX_cleanup(ctx);
/* libctx and propq survive X509_STORE_CTX_cleanup() */
OPENSSL_free(ctx->propq);
OPENSSL_free(ctx);
}
int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
STACK_OF(X509) *chain)
{
if (ctx == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
X509_STORE_CTX_cleanup(ctx);
ctx->store = store;
ctx->cert = x509;
ctx->untrusted = chain;
ctx->crls = NULL;
ctx->num_untrusted = 0;
ctx->other_ctx = NULL;
ctx->valid = 0;
ctx->chain = NULL;
ctx->error = X509_V_OK;
ctx->explicit_policy = 0;
ctx->error_depth = 0;
ctx->current_cert = NULL;
ctx->current_issuer = NULL;
ctx->current_crl = NULL;
ctx->current_crl_score = 0;
ctx->current_reasons = 0;
ctx->tree = NULL;
ctx->parent = NULL;
ctx->dane = NULL;
ctx->bare_ta_signed = 0;
/* Zero ex_data to make sure we're cleanup-safe */
memset(&ctx->ex_data, 0, sizeof(ctx->ex_data));
/* store->cleanup is always 0 in OpenSSL, if set must be idempotent */
if (store != NULL)
ctx->cleanup = store->cleanup;
else
ctx->cleanup = NULL;
if (store != NULL && store->check_issued != NULL)
ctx->check_issued = store->check_issued;
else
ctx->check_issued = check_issued;
if (store != NULL && store->get_issuer != NULL)
ctx->get_issuer = store->get_issuer;
else
ctx->get_issuer = X509_STORE_CTX_get1_issuer;
if (store != NULL && store->verify_cb != NULL)
ctx->verify_cb = store->verify_cb;
else
ctx->verify_cb = null_callback;
if (store != NULL && store->verify != NULL)
ctx->verify = store->verify;
else
ctx->verify = internal_verify;
if (store != NULL && store->check_revocation != NULL)
ctx->check_revocation = store->check_revocation;
else
ctx->check_revocation = check_revocation;
if (store != NULL && store->get_crl != NULL)
ctx->get_crl = store->get_crl;
else
ctx->get_crl = NULL;
if (store != NULL && store->check_crl != NULL)
ctx->check_crl = store->check_crl;
else
ctx->check_crl = check_crl;
if (store != NULL && store->cert_crl != NULL)
ctx->cert_crl = store->cert_crl;
else
ctx->cert_crl = cert_crl;
if (store != NULL && store->check_policy != NULL)
ctx->check_policy = store->check_policy;
else
ctx->check_policy = check_policy;
if (store != NULL && store->lookup_certs != NULL)
ctx->lookup_certs = store->lookup_certs;
else
ctx->lookup_certs = X509_STORE_CTX_get1_certs;
if (store != NULL && store->lookup_crls != NULL)
ctx->lookup_crls = store->lookup_crls;
else
ctx->lookup_crls = X509_STORE_CTX_get1_crls;
ctx->param = X509_VERIFY_PARAM_new();
if (ctx->param == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
/* Inherit callbacks and flags from X509_STORE if not set use defaults. */
if (store == NULL)
ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT | X509_VP_FLAG_ONCE;
else if (X509_VERIFY_PARAM_inherit(ctx->param, store->param) == 0)
goto err;
if (!X509_STORE_CTX_set_default(ctx, "default"))
goto err;
/*
* XXX: For now, continue to inherit trust from VPM, but infer from the
* purpose if this still yields the default value.
*/
if (ctx->param->trust == X509_TRUST_DEFAULT) {
int idx = X509_PURPOSE_get_by_id(ctx->param->purpose);
X509_PURPOSE *xp = X509_PURPOSE_get0(idx);
if (xp != NULL)
ctx->param->trust = X509_PURPOSE_get_trust(xp);
}
if (CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
&ctx->ex_data))
return 1;
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
err:
/*
* On error clean up allocated storage, if the store context was not
* allocated with X509_STORE_CTX_new() this is our last chance to do so.
*/
X509_STORE_CTX_cleanup(ctx);
return 0;
}
/*
* Set alternative get_issuer method: just from a STACK of trusted certificates.
* This avoids the complexity of X509_STORE where it is not needed.
*/
void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
{
ctx->other_ctx = sk;
ctx->get_issuer = get_issuer_sk;
ctx->lookup_certs = lookup_certs_sk;
}
void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
{
/*
* We need to be idempotent because, unfortunately, free() also calls
* cleanup(), so the natural call sequence new(), init(), cleanup(), free()
* calls cleanup() for the same object twice! Thus we must zero the
* pointers below after they're freed!
*/
/* Seems to always be NULL in OpenSSL, do this at most once. */
if (ctx->cleanup != NULL) {
ctx->cleanup(ctx);
ctx->cleanup = NULL;
}
if (ctx->param != NULL) {
if (ctx->parent == NULL)
X509_VERIFY_PARAM_free(ctx->param);
ctx->param = NULL;
}
X509_policy_tree_free(ctx->tree);
ctx->tree = NULL;
sk_X509_pop_free(ctx->chain, X509_free);
ctx->chain = NULL;
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data));
memset(&ctx->ex_data, 0, sizeof(ctx->ex_data));
}
void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth)
{
X509_VERIFY_PARAM_set_depth(ctx->param, depth);
}
void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags)
{
X509_VERIFY_PARAM_set_flags(ctx->param, flags);
}
void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
time_t t)
{
X509_VERIFY_PARAM_set_time(ctx->param, t);
}
X509 *X509_STORE_CTX_get0_cert(const X509_STORE_CTX *ctx)
{
return ctx->cert;
}
STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx)
{
return ctx->untrusted;
}
void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
{
ctx->untrusted = sk;
}
void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
{
sk_X509_pop_free(ctx->chain, X509_free);
ctx->chain = sk;
}
void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
X509_STORE_CTX_verify_cb verify_cb)
{
ctx->verify_cb = verify_cb;
}
X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(const X509_STORE_CTX *ctx)
{
return ctx->verify_cb;
}
void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx,
X509_STORE_CTX_verify_fn verify)
{
ctx->verify = verify;
}
X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(const X509_STORE_CTX *ctx)
{
return ctx->verify;
}
X509_STORE_CTX_get_issuer_fn
X509_STORE_CTX_get_get_issuer(const X509_STORE_CTX *ctx)
{
return ctx->get_issuer;
}
X509_STORE_CTX_check_issued_fn
X509_STORE_CTX_get_check_issued(const X509_STORE_CTX *ctx)
{
return ctx->check_issued;
}
X509_STORE_CTX_check_revocation_fn
X509_STORE_CTX_get_check_revocation(const X509_STORE_CTX *ctx)
{
return ctx->check_revocation;
}
X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(const X509_STORE_CTX *ctx)
{
return ctx->get_crl;
}
X509_STORE_CTX_check_crl_fn
X509_STORE_CTX_get_check_crl(const X509_STORE_CTX *ctx)
{
return ctx->check_crl;
}
X509_STORE_CTX_cert_crl_fn
X509_STORE_CTX_get_cert_crl(const X509_STORE_CTX *ctx)
{
return ctx->cert_crl;
}
X509_STORE_CTX_check_policy_fn
X509_STORE_CTX_get_check_policy(const X509_STORE_CTX *ctx)
{
return ctx->check_policy;
}
X509_STORE_CTX_lookup_certs_fn
X509_STORE_CTX_get_lookup_certs(const X509_STORE_CTX *ctx)
{
return ctx->lookup_certs;
}
X509_STORE_CTX_lookup_crls_fn
X509_STORE_CTX_get_lookup_crls(const X509_STORE_CTX *ctx)
{
return ctx->lookup_crls;
}
X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(const X509_STORE_CTX *ctx)
{
return ctx->cleanup;
}
X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(const X509_STORE_CTX *ctx)
{
return ctx->tree;
}
int X509_STORE_CTX_get_explicit_policy(const X509_STORE_CTX *ctx)
{
return ctx->explicit_policy;
}
int X509_STORE_CTX_get_num_untrusted(const X509_STORE_CTX *ctx)
{
return ctx->num_untrusted;
}
int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name)
{
const X509_VERIFY_PARAM *param;
param = X509_VERIFY_PARAM_lookup(name);
if (param == NULL) {
ERR_raise_data(ERR_LIB_X509, X509_R_UNKNOWN_PURPOSE_ID, "name=%s", name);
return 0;
}
return X509_VERIFY_PARAM_inherit(ctx->param, param);
}
X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(const X509_STORE_CTX *ctx)
{
return ctx->param;
}
void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param)
{
X509_VERIFY_PARAM_free(ctx->param);
ctx->param = param;
}
void X509_STORE_CTX_set0_dane(X509_STORE_CTX *ctx, SSL_DANE *dane)
{
ctx->dane = dane;
}
static unsigned char *dane_i2d(X509 *cert, uint8_t selector,
unsigned int *i2dlen)
{
unsigned char *buf = NULL;
int len;
/*
* Extract ASN.1 DER form of certificate or public key.
*/
switch (selector) {
case DANETLS_SELECTOR_CERT:
len = i2d_X509(cert, &buf);
break;
case DANETLS_SELECTOR_SPKI:
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &buf);
break;
default:
ERR_raise(ERR_LIB_X509, X509_R_BAD_SELECTOR);
return NULL;
}
if (len < 0 || buf == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
*i2dlen = (unsigned int)len;
return buf;
}
#define DANETLS_NONE 256 /* impossible uint8_t */
/* Returns -1 on internal error */
static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth)
{
SSL_DANE *dane = ctx->dane;
unsigned usage = DANETLS_NONE;
unsigned selector = DANETLS_NONE;
unsigned ordinal = DANETLS_NONE;
unsigned mtype = DANETLS_NONE;
unsigned char *i2dbuf = NULL;
unsigned int i2dlen = 0;
unsigned char mdbuf[EVP_MAX_MD_SIZE];
unsigned char *cmpbuf = NULL;
unsigned int cmplen = 0;
int i;
int recnum;
int matched = 0;
danetls_record *t = NULL;
uint32_t mask;
mask = (depth == 0) ? DANETLS_EE_MASK : DANETLS_TA_MASK;
/* The trust store is not applicable with DANE-TA(2) */
if (depth >= ctx->num_untrusted)
mask &= DANETLS_PKIX_MASK;
/*
* If we've previously matched a PKIX-?? record, no need to test any
* further PKIX-?? records, it remains to just build the PKIX chain.
* Had the match been a DANE-?? record, we'd be done already.
*/
if (dane->mdpth >= 0)
mask &= ~DANETLS_PKIX_MASK;
/*-
* https://tools.ietf.org/html/rfc7671#section-5.1
* https://tools.ietf.org/html/rfc7671#section-5.2
* https://tools.ietf.org/html/rfc7671#section-5.3
* https://tools.ietf.org/html/rfc7671#section-5.4
*
* We handle DANE-EE(3) records first as they require no chain building
* and no expiration or hostname checks. We also process digests with
* higher ordinals first and ignore lower priorities except Full(0) which
* is always processed (last). If none match, we then process PKIX-EE(1).
*
* NOTE: This relies on DANE usages sorting before the corresponding PKIX
* usages in SSL_dane_tlsa_add(), and also on descending sorting of digest
* priorities. See twin comment in ssl/ssl_lib.c.
*
* We expect that most TLSA RRsets will have just a single usage, so we
* don't go out of our way to cache multiple selector-specific i2d buffers
* across usages, but if the selector happens to remain the same as switch
* usages, that's OK. Thus, a set of "3 1 1", "3 0 1", "1 1 1", "1 0 1",
* records would result in us generating each of the certificate and public
* key DER forms twice, but more typically we'd just see multiple "3 1 1"
* or multiple "3 0 1" records.
*
* As soon as we find a match at any given depth, we stop, because either
* we've matched a DANE-?? record and the peer is authenticated, or, after
* exhausting all DANE-?? records, we've matched a PKIX-?? record, which is
* sufficient for DANE, and what remains to do is ordinary PKIX validation.
*/
recnum = (dane->umask & mask) != 0 ? sk_danetls_record_num(dane->trecs) : 0;
for (i = 0; matched == 0 && i < recnum; ++i) {
t = sk_danetls_record_value(dane->trecs, i);
if ((DANETLS_USAGE_BIT(t->usage) & mask) == 0)
continue;
if (t->usage != usage) {
usage = t->usage;
/* Reset digest agility for each usage/selector pair */
mtype = DANETLS_NONE;
ordinal = dane->dctx->mdord[t->mtype];
}
if (t->selector != selector) {
selector = t->selector;
/* Update per-selector state */
OPENSSL_free(i2dbuf);
i2dbuf = dane_i2d(cert, selector, &i2dlen);
if (i2dbuf == NULL)
return -1;
/* Reset digest agility for each usage/selector pair */
mtype = DANETLS_NONE;
ordinal = dane->dctx->mdord[t->mtype];
} else if (t->mtype != DANETLS_MATCHING_FULL) {
/*-
* Digest agility:
*
* <https://tools.ietf.org/html/rfc7671#section-9>
*
* For a fixed selector, after processing all records with the
* highest mtype ordinal, ignore all mtypes with lower ordinals
* other than "Full".
*/
if (dane->dctx->mdord[t->mtype] < ordinal)
continue;
}
/*
* Each time we hit a (new selector or) mtype, re-compute the relevant
* digest, more complex caching is not worth the code space.
*/
if (t->mtype != mtype) {
const EVP_MD *md = dane->dctx->mdevp[mtype = t->mtype];
cmpbuf = i2dbuf;
cmplen = i2dlen;
if (md != NULL) {
cmpbuf = mdbuf;
if (!EVP_Digest(i2dbuf, i2dlen, cmpbuf, &cmplen, md, 0)) {
matched = -1;
break;
}
}
}
/*
* Squirrel away the certificate and depth if we have a match. Any
* DANE match is dispositive, but with PKIX we still need to build a
* full chain.
*/
if (cmplen == t->dlen &&
memcmp(cmpbuf, t->data, cmplen) == 0) {
if (DANETLS_USAGE_BIT(usage) & DANETLS_DANE_MASK)
matched = 1;
if (matched || dane->mdpth < 0) {
dane->mdpth = depth;
dane->mtlsa = t;
OPENSSL_free(dane->mcert);
dane->mcert = cert;
X509_up_ref(cert);
}
break;
}
}
/* Clear the one-element DER cache */
OPENSSL_free(i2dbuf);
return matched;
}
/* Returns -1 on internal error */
static int check_dane_issuer(X509_STORE_CTX *ctx, int depth)
{
SSL_DANE *dane = ctx->dane;
int matched = 0;
X509 *cert;
if (!DANETLS_HAS_TA(dane) || depth == 0)
return X509_TRUST_UNTRUSTED;
/*
* Record any DANE trust anchor matches, for the first depth to test, if
* there's one at that depth. (This'll be false for length 1 chains looking
* for an exact match for the leaf certificate).
*/
cert = sk_X509_value(ctx->chain, depth);
if (cert != NULL && (matched = dane_match(ctx, cert, depth)) < 0)
return matched;
if (matched > 0) {
ctx->num_untrusted = depth - 1;
return X509_TRUST_TRUSTED;
}
return X509_TRUST_UNTRUSTED;
}
static int check_dane_pkeys(X509_STORE_CTX *ctx)
{
SSL_DANE *dane = ctx->dane;
danetls_record *t;
int num = ctx->num_untrusted;
X509 *cert = sk_X509_value(ctx->chain, num - 1);
int recnum = sk_danetls_record_num(dane->trecs);
int i;
for (i = 0; i < recnum; ++i) {
t = sk_danetls_record_value(dane->trecs, i);
if (t->usage != DANETLS_USAGE_DANE_TA ||
t->selector != DANETLS_SELECTOR_SPKI ||
t->mtype != DANETLS_MATCHING_FULL ||
X509_verify(cert, t->spki) <= 0)
continue;
/* Clear any PKIX-?? matches that failed to extend to a full chain */
X509_free(dane->mcert);
dane->mcert = NULL;
/* Record match via a bare TA public key */
ctx->bare_ta_signed = 1;
dane->mdpth = num - 1;
dane->mtlsa = t;
/* Prune any excess chain certificates */
num = sk_X509_num(ctx->chain);
for (; num > ctx->num_untrusted; --num)
X509_free(sk_X509_pop(ctx->chain));
return X509_TRUST_TRUSTED;
}
return X509_TRUST_UNTRUSTED;
}
static void dane_reset(SSL_DANE *dane)
{
/* Reset state to verify another chain, or clear after failure. */
X509_free(dane->mcert);
dane->mcert = NULL;
dane->mtlsa = NULL;
dane->mdpth = -1;
dane->pdpth = -1;
}
static int check_leaf_suiteb(X509_STORE_CTX *ctx, X509 *cert)
{
int err = X509_chain_check_suiteb(NULL, cert, NULL, ctx->param->flags);
CB_FAIL_IF(err != X509_V_OK, ctx, cert, 0, err);
return 1;
}
/* Returns -1 on internal error */
static int dane_verify(X509_STORE_CTX *ctx)
{
X509 *cert = ctx->cert;
SSL_DANE *dane = ctx->dane;
int matched;
int done;
dane_reset(dane);
/*-
* When testing the leaf certificate, if we match a DANE-EE(3) record,
* dane_match() returns 1 and we're done. If however we match a PKIX-EE(1)
* record, the match depth and matching TLSA record are recorded, but the
* return value is 0, because we still need to find a PKIX trust anchor.
* Therefore, when DANE authentication is enabled (required), we're done
* if:
* + matched < 0, internal error.
* + matched == 1, we matched a DANE-EE(3) record
* + matched == 0, mdepth < 0 (no PKIX-EE match) and there are no
* DANE-TA(2) or PKIX-TA(0) to test.
*/
matched = dane_match(ctx, ctx->cert, 0);
done = matched != 0 || (!DANETLS_HAS_TA(dane) && dane->mdpth < 0);
if (done && !X509_get_pubkey_parameters(NULL, ctx->chain))
return -1;
if (matched > 0) {
/* Callback invoked as needed */
if (!check_leaf_suiteb(ctx, cert))
return 0;
/* Callback invoked as needed */
if ((dane->flags & DANE_FLAG_NO_DANE_EE_NAMECHECKS) == 0 &&
!check_id(ctx))
return 0;
/* Bypass internal_verify(), issue depth 0 success callback */
ctx->error_depth = 0;
ctx->current_cert = cert;
return ctx->verify_cb(1, ctx);
}
if (matched < 0) {
ctx->error_depth = 0;
ctx->current_cert = cert;
ctx->error = X509_V_ERR_OUT_OF_MEM;
return -1;
}
if (done) {
/* Fail early, TA-based success is not possible */
if (!check_leaf_suiteb(ctx, cert))
return 0;
return verify_cb_cert(ctx, cert, 0, X509_V_ERR_DANE_NO_MATCH);
}
/*
* Chain verification for usages 0/1/2. TLSA record matching of depth > 0
* certificates happens in-line with building the rest of the chain.
*/
return verify_chain(ctx);
}
/*
* Get trusted issuer, without duplicate suppression
* Returns -1 on internal error.
*/
static int get1_trusted_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *cert)
{
STACK_OF(X509) *saved_chain = ctx->chain;
int ok;
ctx->chain = NULL;
ok = ctx->get_issuer(issuer, ctx, cert);
ctx->chain = saved_chain;
return ok;
}
/* Returns -1 on internal error */
static int build_chain(X509_STORE_CTX *ctx)
{
SSL_DANE *dane = ctx->dane;
int num = sk_X509_num(ctx->chain);
STACK_OF(X509) *sk_untrusted = NULL;
unsigned int search;
int may_trusted = 0;
int may_alternate = 0;
int trust = X509_TRUST_UNTRUSTED;
int alt_untrusted = 0;
int max_depth;
int ok = 0;
int i;
/* Our chain starts with a single untrusted element. */
if (!ossl_assert(num == 1 && ctx->num_untrusted == num))
goto int_err;
#define S_DOUNTRUSTED (1 << 0) /* Search untrusted chain */
#define S_DOTRUSTED (1 << 1) /* Search trusted store */
#define S_DOALTERNATE (1 << 2) /* Retry with pruned alternate chain */
/*
* Set up search policy, untrusted if possible, trusted-first if enabled,
* which is the default.
* If we're doing DANE and not doing PKIX-TA/PKIX-EE, we never look in the
* trust_store, otherwise we might look there first. If not trusted-first,
* and alternate chains are not disabled, try building an alternate chain
* if no luck with untrusted first.
*/
search = ctx->untrusted != NULL ? S_DOUNTRUSTED : 0;
if (DANETLS_HAS_PKIX(dane) || !DANETLS_HAS_DANE(dane)) {
if (search == 0 || (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) != 0)
search |= S_DOTRUSTED;
else if (!(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS))
may_alternate = 1;
may_trusted = 1;
}
/* Initialize empty untrusted stack. */
if ((sk_untrusted = sk_X509_new_null()) == NULL)
goto memerr;
/*
* If we got any "Cert(0) Full(0)" trust anchors from DNS, *prepend* them
* to our working copy of the untrusted certificate stack.
*/
if (DANETLS_ENABLED(dane) && dane->certs != NULL
&& !X509_add_certs(sk_untrusted, dane->certs, X509_ADD_FLAG_DEFAULT))
goto memerr;
/*
* Shallow-copy the stack of untrusted certificates (with TLS, this is
* typically the content of the peer's certificate message) so we can make
* multiple passes over it, while free to remove elements as we go.
*/
if (!X509_add_certs(sk_untrusted, ctx->untrusted, X509_ADD_FLAG_DEFAULT))
goto memerr;
/*
* Still absurdly large, but arithmetically safe, a lower hard upper bound
* might be reasonable.
*/
if (ctx->param->depth > INT_MAX / 2)
ctx->param->depth = INT_MAX / 2;
/*
* Try to extend the chain until we reach an ultimately trusted issuer.
* Build chains up to one longer the limit, later fail if we hit the limit,
* with an X509_V_ERR_CERT_CHAIN_TOO_LONG error code.
*/
max_depth = ctx->param->depth + 1;
while (search != 0) {
X509 *curr, *issuer = NULL;
num = sk_X509_num(ctx->chain);
ctx->error_depth = num - 1;
/*
* Look in the trust store if enabled for first lookup, or we've run
* out of untrusted issuers and search here is not disabled. When we
* reach the depth limit, we stop extending the chain, if by that point
* we've not found a trust anchor, any trusted chain would be too long.
*
* The error reported to the application verify callback is at the
* maximal valid depth with the current certificate equal to the last
* not ultimately-trusted issuer. For example, with verify_depth = 0,
* the callback will report errors at depth=1 when the immediate issuer
* of the leaf certificate is not a trust anchor. No attempt will be
* made to locate an issuer for that certificate, since such a chain
* would be a-priori too long.
*/
if ((search & S_DOTRUSTED) != 0) {
i = num;
if ((search & S_DOALTERNATE) != 0) {
/*
* As high up the chain as we can, look for an alternative
* trusted issuer of an untrusted certificate that currently
* has an untrusted issuer. We use the alt_untrusted variable
* to track how far up the chain we find the first match. It
* is only if and when we find a match, that we prune the chain
* and reset ctx->num_untrusted to the reduced count of
* untrusted certificates. While we're searching for such a
* match (which may never be found), it is neither safe nor
* wise to preemptively modify either the chain or
* ctx->num_untrusted.
*
* Note, like ctx->num_untrusted, alt_untrusted is a count of
* untrusted certificates, not a "depth".
*/
i = alt_untrusted;
}
curr = sk_X509_value(ctx->chain, i - 1);
/* Note: get1_trusted_issuer() must be used even if self-signed. */
ok = num > max_depth ? 0 : get1_trusted_issuer(&issuer, ctx, curr);
if (ok < 0) {
trust = -1;
ctx->error = X509_V_ERR_STORE_LOOKUP;
break;
}
if (ok > 0) {
int self_signed = X509_self_signed(curr, 0);
if (self_signed < 0) {
X509_free(issuer);
goto int_err;
}
/*
* Alternative trusted issuer for a mid-chain untrusted cert?
* Pop the untrusted cert's successors and retry. We might now
* be able to complete a valid chain via the trust store. Note
* that despite the current trust store match we might still
* fail complete the chain to a suitable trust anchor, in which
* case we may prune some more untrusted certificates and try
* again. Thus the S_DOALTERNATE bit may yet be turned on
* again with an even shorter untrusted chain!
*
* If in the process we threw away our matching PKIX-TA trust
* anchor, reset DANE trust. We might find a suitable trusted
* certificate among the ones from the trust store.
*/
if ((search & S_DOALTERNATE) != 0) {
if (!ossl_assert(num > i && i > 0 && !self_signed)) {
X509_free(issuer);
goto int_err;
}
search &= ~S_DOALTERNATE;
for (; num > i; --num)
X509_free(sk_X509_pop(ctx->chain));
ctx->num_untrusted = num;
if (DANETLS_ENABLED(dane) &&
dane->mdpth >= ctx->num_untrusted) {
dane->mdpth = -1;
X509_free(dane->mcert);
dane->mcert = NULL;
}
if (DANETLS_ENABLED(dane) &&
dane->pdpth >= ctx->num_untrusted)
dane->pdpth = -1;
}
/*
* Self-signed untrusted certificates get replaced by their
* trusted matching issuer. Otherwise, grow the chain.
*/
if (!self_signed) {
if (!sk_X509_push(ctx->chain, issuer)) {
X509_free(issuer);
goto memerr;
}
if ((self_signed = X509_self_signed(issuer, 0)) < 0)
goto int_err;
} else {
/*
* We have a self-signed certificate that has the same
* subject name (and perhaps keyid and/or serial number) as
* a trust anchor. We must have an exact match to avoid
* possible impersonation via key substitution etc.
*/
if (X509_cmp(curr, issuer) != 0) {
/* Self-signed untrusted mimic. */
X509_free(issuer);
ok = 0;
} else { /* curr "==" issuer */
X509_free(curr);
ctx->num_untrusted = --num;
(void)sk_X509_set(ctx->chain, num, issuer);
}
}
/*
* We've added a new trusted certificate to the chain, re-check
* trust. If not done, and not self-signed look deeper.
* Whether or not we're doing "trusted first", we no longer
* look for untrusted certificates from the peer's chain.
*
* At this point ctx->num_trusted and num must reflect the
* correct number of untrusted certificates, since the DANE
* logic in check_trust() depends on distinguishing CAs from
* "the wire" from CAs from the trust store. In particular, the
* certificate at depth "num" should be the new trusted
* certificate with ctx->num_untrusted <= num.
*/
if (ok) {
if (!ossl_assert(ctx->num_untrusted <= num))
goto int_err;
search &= ~S_DOUNTRUSTED;
trust = check_trust(ctx, num);
if (trust != X509_TRUST_UNTRUSTED)
break;
if (!self_signed)
continue;
}
}
/*
* No dispositive decision, and either self-signed or no match, if
* we were doing untrusted-first, and alt-chains are not disabled,
* do that, by repeatedly losing one untrusted element at a time,
* and trying to extend the shorted chain.
*/
if ((search & S_DOUNTRUSTED) == 0) {
/* Continue search for a trusted issuer of a shorter chain? */
if ((search & S_DOALTERNATE) != 0 && --alt_untrusted > 0)
continue;
/* Still no luck and no fallbacks left? */
if (!may_alternate || (search & S_DOALTERNATE) != 0 ||
ctx->num_untrusted < 2)
break;
/* Search for a trusted issuer of a shorter chain */
search |= S_DOALTERNATE;
alt_untrusted = ctx->num_untrusted - 1;
}
}
/*
* Extend chain with peer-provided untrusted certificates
*/
if ((search & S_DOUNTRUSTED) != 0) {
num = sk_X509_num(ctx->chain);
if (!ossl_assert(num == ctx->num_untrusted))
goto int_err;
curr = sk_X509_value(ctx->chain, num - 1);
issuer = (X509_self_signed(curr, 0) > 0 || num > max_depth) ?
NULL : find_issuer(ctx, sk_untrusted, curr);
if (issuer == NULL) {
/*
* Once we have reached a self-signed cert or num > max_depth
* or can't find an issuer in the untrusted list we stop looking
* there and start looking only in the trust store if enabled.
*/
search &= ~S_DOUNTRUSTED;
if (may_trusted)
search |= S_DOTRUSTED;
continue;
}
/* Drop this issuer from future consideration */
(void)sk_X509_delete_ptr(sk_untrusted, issuer);
if (!X509_add_cert(ctx->chain, issuer, X509_ADD_FLAG_UP_REF))
goto int_err;
++ctx->num_untrusted;
/* Check for DANE-TA trust of the topmost untrusted certificate. */
trust = check_dane_issuer(ctx, ctx->num_untrusted - 1);
if (trust == X509_TRUST_TRUSTED || trust == X509_TRUST_REJECTED)
break;
}
}
sk_X509_free(sk_untrusted);
if (trust < 0) /* internal error */
return trust;
/*
* Last chance to make a trusted chain, either bare DANE-TA public-key
* signers, or else direct leaf PKIX trust.
*/
num = sk_X509_num(ctx->chain);
if (num <= max_depth) {
if (trust == X509_TRUST_UNTRUSTED && DANETLS_HAS_DANE_TA(dane))
trust = check_dane_pkeys(ctx);
if (trust == X509_TRUST_UNTRUSTED && num == ctx->num_untrusted)
trust = check_trust(ctx, num);
}
switch (trust) {
case X509_TRUST_TRUSTED:
return 1;
case X509_TRUST_REJECTED:
/* Callback already issued */
return 0;
case X509_TRUST_UNTRUSTED:
default:
switch(ctx->error) {
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
case X509_V_ERR_CERT_NOT_YET_VALID:
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
case X509_V_ERR_CERT_HAS_EXPIRED:
return 0; /* Callback already issued by ossl_x509_check_cert_time() */
default: /* A preliminary error has become final */
return verify_cb_cert(ctx, NULL, num - 1, ctx->error);
case X509_V_OK:
break;
}
CB_FAIL_IF(num > max_depth,
ctx, NULL, num - 1, X509_V_ERR_CERT_CHAIN_TOO_LONG);
CB_FAIL_IF(DANETLS_ENABLED(dane)
&& (!DANETLS_HAS_PKIX(dane) || dane->pdpth >= 0),
ctx, NULL, num - 1, X509_V_ERR_DANE_NO_MATCH);
if (X509_self_signed(sk_X509_value(ctx->chain, num - 1), 0) > 0)
return verify_cb_cert(ctx, NULL, num - 1,
num == 1
? X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
: X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN);
return verify_cb_cert(ctx, NULL, num - 1,
ctx->num_untrusted < num
? X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
: X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY);
}
int_err:
ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
ctx->error = X509_V_ERR_UNSPECIFIED;
sk_X509_free(sk_untrusted);
return -1;
memerr:
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
sk_X509_free(sk_untrusted);
return -1;
}
STACK_OF(X509) *X509_build_chain(X509 *target, STACK_OF(X509) *certs,
X509_STORE *store, int with_self_signed,
OSSL_LIB_CTX *libctx, const char *propq)
{
int finish_chain = store != NULL;
X509_STORE_CTX *ctx;
int flags = X509_ADD_FLAG_UP_REF;
STACK_OF(X509) *result = NULL;
if (target == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if ((ctx = X509_STORE_CTX_new_ex(libctx, propq)) == NULL)
return NULL;
if (!X509_STORE_CTX_init(ctx, store, target, finish_chain ? certs : NULL))
goto err;
if (!finish_chain)
X509_STORE_CTX_set0_trusted_stack(ctx, certs);
if (!ossl_x509_add_cert_new(&ctx->chain, target, X509_ADD_FLAG_UP_REF)) {
ctx->error = X509_V_ERR_OUT_OF_MEM;
goto err;
}
ctx->num_untrusted = 1;
if (!build_chain(ctx) && finish_chain)
goto err;
/* result list to store the up_ref'ed certificates */
if (sk_X509_num(ctx->chain) > 1 && !with_self_signed)
flags |= X509_ADD_FLAG_NO_SS;
if (!ossl_x509_add_certs_new(&result, ctx->chain, flags)) {
sk_X509_free(result);
result = NULL;
}
err:
X509_STORE_CTX_free(ctx);
return result;
}
/*
* note that there's a corresponding minbits_table in ssl/ssl_cert.c
* in ssl_get_security_level_bits that's used for selection of DH parameters
*/
static const int minbits_table[] = { 80, 112, 128, 192, 256 };
static const int NUM_AUTH_LEVELS = OSSL_NELEM(minbits_table);
/*-
* Check whether the public key of `cert` meets the security level of `ctx`.
* Returns 1 on success, 0 otherwise.
*/
static int check_key_level(X509_STORE_CTX *ctx, X509 *cert)
{
EVP_PKEY *pkey = X509_get0_pubkey(cert);
int level = ctx->param->auth_level;
/*
* At security level zero, return without checking for a supported public
* key type. Some engines support key types not understood outside the
* engine, and we only need to understand the key when enforcing a security
* floor.
*/
if (level <= 0)
return 1;
/* Unsupported or malformed keys are not secure */
if (pkey == NULL)
return 0;
if (level > NUM_AUTH_LEVELS)
level = NUM_AUTH_LEVELS;
return EVP_PKEY_get_security_bits(pkey) >= minbits_table[level - 1];
}
/*-
* Check whether the public key of ``cert`` does not use explicit params
* for an elliptic curve.
*
* Returns 1 on success, 0 if check fails, -1 for other errors.
*/
static int check_curve(X509 *cert)
{
EVP_PKEY *pkey = X509_get0_pubkey(cert);
/* Unsupported or malformed key */
if (pkey == NULL)
return -1;
if (EVP_PKEY_get_id(pkey) == EVP_PKEY_EC) {
int ret, val;
ret = EVP_PKEY_get_int_param(pkey,
OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS,
&val);
- return ret < 0 ? ret : !val;
+ return ret == 1 ? !val : -1;
}
return 1;
}
/*-
* Check whether the signature digest algorithm of ``cert`` meets the security
* level of ``ctx``. Should not be checked for trust anchors (whether
* self-signed or otherwise).
*
* Returns 1 on success, 0 otherwise.
*/
static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert)
{
int secbits = -1;
int level = ctx->param->auth_level;
if (level <= 0)
return 1;
if (level > NUM_AUTH_LEVELS)
level = NUM_AUTH_LEVELS;
if (!X509_get_signature_info(cert, NULL, NULL, &secbits, NULL))
return 0;
return secbits >= minbits_table[level - 1];
}
diff --git a/doc/build.info b/doc/build.info
index ec8778f2ac69..00dc150721ac 100644
--- a/doc/build.info
+++ b/doc/build.info
@@ -1,4860 +1,4872 @@
SUBDIRS = man1
DEPEND[html/man1/CA.pl.html]=man1/CA.pl.pod
GENERATE[html/man1/CA.pl.html]=man1/CA.pl.pod
DEPEND[man/man1/CA.pl.1]=man1/CA.pl.pod
GENERATE[man/man1/CA.pl.1]=man1/CA.pl.pod
DEPEND[html/man1/openssl-asn1parse.html]=man1/openssl-asn1parse.pod
GENERATE[html/man1/openssl-asn1parse.html]=man1/openssl-asn1parse.pod
DEPEND[man/man1/openssl-asn1parse.1]=man1/openssl-asn1parse.pod
GENERATE[man/man1/openssl-asn1parse.1]=man1/openssl-asn1parse.pod
DEPEND[man1/openssl-asn1parse.pod]{pod}=man1/openssl-asn1parse.pod.in
GENERATE[man1/openssl-asn1parse.pod]=man1/openssl-asn1parse.pod.in
DEPEND[html/man1/openssl-ca.html]=man1/openssl-ca.pod
GENERATE[html/man1/openssl-ca.html]=man1/openssl-ca.pod
DEPEND[man/man1/openssl-ca.1]=man1/openssl-ca.pod
GENERATE[man/man1/openssl-ca.1]=man1/openssl-ca.pod
DEPEND[man1/openssl-ca.pod]{pod}=man1/openssl-ca.pod.in
GENERATE[man1/openssl-ca.pod]=man1/openssl-ca.pod.in
DEPEND[html/man1/openssl-ciphers.html]=man1/openssl-ciphers.pod
GENERATE[html/man1/openssl-ciphers.html]=man1/openssl-ciphers.pod
DEPEND[man/man1/openssl-ciphers.1]=man1/openssl-ciphers.pod
GENERATE[man/man1/openssl-ciphers.1]=man1/openssl-ciphers.pod
DEPEND[man1/openssl-ciphers.pod]{pod}=man1/openssl-ciphers.pod.in
GENERATE[man1/openssl-ciphers.pod]=man1/openssl-ciphers.pod.in
DEPEND[html/man1/openssl-cmds.html]=man1/openssl-cmds.pod
GENERATE[html/man1/openssl-cmds.html]=man1/openssl-cmds.pod
DEPEND[man/man1/openssl-cmds.1]=man1/openssl-cmds.pod
GENERATE[man/man1/openssl-cmds.1]=man1/openssl-cmds.pod
DEPEND[man1/openssl-cmds.pod]{pod}=man1/openssl-cmds.pod.in
GENERATE[man1/openssl-cmds.pod]=man1/openssl-cmds.pod.in
DEPEND[html/man1/openssl-cmp.html]=man1/openssl-cmp.pod
GENERATE[html/man1/openssl-cmp.html]=man1/openssl-cmp.pod
DEPEND[man/man1/openssl-cmp.1]=man1/openssl-cmp.pod
GENERATE[man/man1/openssl-cmp.1]=man1/openssl-cmp.pod
DEPEND[man1/openssl-cmp.pod]{pod}=man1/openssl-cmp.pod.in
GENERATE[man1/openssl-cmp.pod]=man1/openssl-cmp.pod.in
DEPEND[html/man1/openssl-cms.html]=man1/openssl-cms.pod
GENERATE[html/man1/openssl-cms.html]=man1/openssl-cms.pod
DEPEND[man/man1/openssl-cms.1]=man1/openssl-cms.pod
GENERATE[man/man1/openssl-cms.1]=man1/openssl-cms.pod
DEPEND[man1/openssl-cms.pod]{pod}=man1/openssl-cms.pod.in
GENERATE[man1/openssl-cms.pod]=man1/openssl-cms.pod.in
DEPEND[html/man1/openssl-crl.html]=man1/openssl-crl.pod
GENERATE[html/man1/openssl-crl.html]=man1/openssl-crl.pod
DEPEND[man/man1/openssl-crl.1]=man1/openssl-crl.pod
GENERATE[man/man1/openssl-crl.1]=man1/openssl-crl.pod
DEPEND[man1/openssl-crl.pod]{pod}=man1/openssl-crl.pod.in
GENERATE[man1/openssl-crl.pod]=man1/openssl-crl.pod.in
DEPEND[html/man1/openssl-crl2pkcs7.html]=man1/openssl-crl2pkcs7.pod
GENERATE[html/man1/openssl-crl2pkcs7.html]=man1/openssl-crl2pkcs7.pod
DEPEND[man/man1/openssl-crl2pkcs7.1]=man1/openssl-crl2pkcs7.pod
GENERATE[man/man1/openssl-crl2pkcs7.1]=man1/openssl-crl2pkcs7.pod
DEPEND[man1/openssl-crl2pkcs7.pod]{pod}=man1/openssl-crl2pkcs7.pod.in
GENERATE[man1/openssl-crl2pkcs7.pod]=man1/openssl-crl2pkcs7.pod.in
DEPEND[html/man1/openssl-dgst.html]=man1/openssl-dgst.pod
GENERATE[html/man1/openssl-dgst.html]=man1/openssl-dgst.pod
DEPEND[man/man1/openssl-dgst.1]=man1/openssl-dgst.pod
GENERATE[man/man1/openssl-dgst.1]=man1/openssl-dgst.pod
DEPEND[man1/openssl-dgst.pod]{pod}=man1/openssl-dgst.pod.in
GENERATE[man1/openssl-dgst.pod]=man1/openssl-dgst.pod.in
DEPEND[html/man1/openssl-dhparam.html]=man1/openssl-dhparam.pod
GENERATE[html/man1/openssl-dhparam.html]=man1/openssl-dhparam.pod
DEPEND[man/man1/openssl-dhparam.1]=man1/openssl-dhparam.pod
GENERATE[man/man1/openssl-dhparam.1]=man1/openssl-dhparam.pod
DEPEND[man1/openssl-dhparam.pod]{pod}=man1/openssl-dhparam.pod.in
GENERATE[man1/openssl-dhparam.pod]=man1/openssl-dhparam.pod.in
DEPEND[html/man1/openssl-dsa.html]=man1/openssl-dsa.pod
GENERATE[html/man1/openssl-dsa.html]=man1/openssl-dsa.pod
DEPEND[man/man1/openssl-dsa.1]=man1/openssl-dsa.pod
GENERATE[man/man1/openssl-dsa.1]=man1/openssl-dsa.pod
DEPEND[man1/openssl-dsa.pod]{pod}=man1/openssl-dsa.pod.in
GENERATE[man1/openssl-dsa.pod]=man1/openssl-dsa.pod.in
DEPEND[html/man1/openssl-dsaparam.html]=man1/openssl-dsaparam.pod
GENERATE[html/man1/openssl-dsaparam.html]=man1/openssl-dsaparam.pod
DEPEND[man/man1/openssl-dsaparam.1]=man1/openssl-dsaparam.pod
GENERATE[man/man1/openssl-dsaparam.1]=man1/openssl-dsaparam.pod
DEPEND[man1/openssl-dsaparam.pod]{pod}=man1/openssl-dsaparam.pod.in
GENERATE[man1/openssl-dsaparam.pod]=man1/openssl-dsaparam.pod.in
DEPEND[html/man1/openssl-ec.html]=man1/openssl-ec.pod
GENERATE[html/man1/openssl-ec.html]=man1/openssl-ec.pod
DEPEND[man/man1/openssl-ec.1]=man1/openssl-ec.pod
GENERATE[man/man1/openssl-ec.1]=man1/openssl-ec.pod
DEPEND[man1/openssl-ec.pod]{pod}=man1/openssl-ec.pod.in
GENERATE[man1/openssl-ec.pod]=man1/openssl-ec.pod.in
DEPEND[html/man1/openssl-ecparam.html]=man1/openssl-ecparam.pod
GENERATE[html/man1/openssl-ecparam.html]=man1/openssl-ecparam.pod
DEPEND[man/man1/openssl-ecparam.1]=man1/openssl-ecparam.pod
GENERATE[man/man1/openssl-ecparam.1]=man1/openssl-ecparam.pod
DEPEND[man1/openssl-ecparam.pod]{pod}=man1/openssl-ecparam.pod.in
GENERATE[man1/openssl-ecparam.pod]=man1/openssl-ecparam.pod.in
DEPEND[html/man1/openssl-enc.html]=man1/openssl-enc.pod
GENERATE[html/man1/openssl-enc.html]=man1/openssl-enc.pod
DEPEND[man/man1/openssl-enc.1]=man1/openssl-enc.pod
GENERATE[man/man1/openssl-enc.1]=man1/openssl-enc.pod
DEPEND[man1/openssl-enc.pod]{pod}=man1/openssl-enc.pod.in
GENERATE[man1/openssl-enc.pod]=man1/openssl-enc.pod.in
DEPEND[html/man1/openssl-engine.html]=man1/openssl-engine.pod
GENERATE[html/man1/openssl-engine.html]=man1/openssl-engine.pod
DEPEND[man/man1/openssl-engine.1]=man1/openssl-engine.pod
GENERATE[man/man1/openssl-engine.1]=man1/openssl-engine.pod
DEPEND[man1/openssl-engine.pod]{pod}=man1/openssl-engine.pod.in
GENERATE[man1/openssl-engine.pod]=man1/openssl-engine.pod.in
DEPEND[html/man1/openssl-errstr.html]=man1/openssl-errstr.pod
GENERATE[html/man1/openssl-errstr.html]=man1/openssl-errstr.pod
DEPEND[man/man1/openssl-errstr.1]=man1/openssl-errstr.pod
GENERATE[man/man1/openssl-errstr.1]=man1/openssl-errstr.pod
DEPEND[man1/openssl-errstr.pod]{pod}=man1/openssl-errstr.pod.in
GENERATE[man1/openssl-errstr.pod]=man1/openssl-errstr.pod.in
DEPEND[html/man1/openssl-fipsinstall.html]=man1/openssl-fipsinstall.pod
GENERATE[html/man1/openssl-fipsinstall.html]=man1/openssl-fipsinstall.pod
DEPEND[man/man1/openssl-fipsinstall.1]=man1/openssl-fipsinstall.pod
GENERATE[man/man1/openssl-fipsinstall.1]=man1/openssl-fipsinstall.pod
DEPEND[man1/openssl-fipsinstall.pod]{pod}=man1/openssl-fipsinstall.pod.in
GENERATE[man1/openssl-fipsinstall.pod]=man1/openssl-fipsinstall.pod.in
DEPEND[html/man1/openssl-format-options.html]=man1/openssl-format-options.pod
GENERATE[html/man1/openssl-format-options.html]=man1/openssl-format-options.pod
DEPEND[man/man1/openssl-format-options.1]=man1/openssl-format-options.pod
GENERATE[man/man1/openssl-format-options.1]=man1/openssl-format-options.pod
DEPEND[html/man1/openssl-gendsa.html]=man1/openssl-gendsa.pod
GENERATE[html/man1/openssl-gendsa.html]=man1/openssl-gendsa.pod
DEPEND[man/man1/openssl-gendsa.1]=man1/openssl-gendsa.pod
GENERATE[man/man1/openssl-gendsa.1]=man1/openssl-gendsa.pod
DEPEND[man1/openssl-gendsa.pod]{pod}=man1/openssl-gendsa.pod.in
GENERATE[man1/openssl-gendsa.pod]=man1/openssl-gendsa.pod.in
DEPEND[html/man1/openssl-genpkey.html]=man1/openssl-genpkey.pod
GENERATE[html/man1/openssl-genpkey.html]=man1/openssl-genpkey.pod
DEPEND[man/man1/openssl-genpkey.1]=man1/openssl-genpkey.pod
GENERATE[man/man1/openssl-genpkey.1]=man1/openssl-genpkey.pod
DEPEND[man1/openssl-genpkey.pod]{pod}=man1/openssl-genpkey.pod.in
GENERATE[man1/openssl-genpkey.pod]=man1/openssl-genpkey.pod.in
DEPEND[html/man1/openssl-genrsa.html]=man1/openssl-genrsa.pod
GENERATE[html/man1/openssl-genrsa.html]=man1/openssl-genrsa.pod
DEPEND[man/man1/openssl-genrsa.1]=man1/openssl-genrsa.pod
GENERATE[man/man1/openssl-genrsa.1]=man1/openssl-genrsa.pod
DEPEND[man1/openssl-genrsa.pod]{pod}=man1/openssl-genrsa.pod.in
GENERATE[man1/openssl-genrsa.pod]=man1/openssl-genrsa.pod.in
DEPEND[html/man1/openssl-info.html]=man1/openssl-info.pod
GENERATE[html/man1/openssl-info.html]=man1/openssl-info.pod
DEPEND[man/man1/openssl-info.1]=man1/openssl-info.pod
GENERATE[man/man1/openssl-info.1]=man1/openssl-info.pod
DEPEND[man1/openssl-info.pod]{pod}=man1/openssl-info.pod.in
GENERATE[man1/openssl-info.pod]=man1/openssl-info.pod.in
DEPEND[html/man1/openssl-kdf.html]=man1/openssl-kdf.pod
GENERATE[html/man1/openssl-kdf.html]=man1/openssl-kdf.pod
DEPEND[man/man1/openssl-kdf.1]=man1/openssl-kdf.pod
GENERATE[man/man1/openssl-kdf.1]=man1/openssl-kdf.pod
DEPEND[man1/openssl-kdf.pod]{pod}=man1/openssl-kdf.pod.in
GENERATE[man1/openssl-kdf.pod]=man1/openssl-kdf.pod.in
DEPEND[html/man1/openssl-list.html]=man1/openssl-list.pod
GENERATE[html/man1/openssl-list.html]=man1/openssl-list.pod
DEPEND[man/man1/openssl-list.1]=man1/openssl-list.pod
GENERATE[man/man1/openssl-list.1]=man1/openssl-list.pod
DEPEND[man1/openssl-list.pod]{pod}=man1/openssl-list.pod.in
GENERATE[man1/openssl-list.pod]=man1/openssl-list.pod.in
DEPEND[html/man1/openssl-mac.html]=man1/openssl-mac.pod
GENERATE[html/man1/openssl-mac.html]=man1/openssl-mac.pod
DEPEND[man/man1/openssl-mac.1]=man1/openssl-mac.pod
GENERATE[man/man1/openssl-mac.1]=man1/openssl-mac.pod
DEPEND[man1/openssl-mac.pod]{pod}=man1/openssl-mac.pod.in
GENERATE[man1/openssl-mac.pod]=man1/openssl-mac.pod.in
DEPEND[html/man1/openssl-namedisplay-options.html]=man1/openssl-namedisplay-options.pod
GENERATE[html/man1/openssl-namedisplay-options.html]=man1/openssl-namedisplay-options.pod
DEPEND[man/man1/openssl-namedisplay-options.1]=man1/openssl-namedisplay-options.pod
GENERATE[man/man1/openssl-namedisplay-options.1]=man1/openssl-namedisplay-options.pod
DEPEND[html/man1/openssl-nseq.html]=man1/openssl-nseq.pod
GENERATE[html/man1/openssl-nseq.html]=man1/openssl-nseq.pod
DEPEND[man/man1/openssl-nseq.1]=man1/openssl-nseq.pod
GENERATE[man/man1/openssl-nseq.1]=man1/openssl-nseq.pod
DEPEND[man1/openssl-nseq.pod]{pod}=man1/openssl-nseq.pod.in
GENERATE[man1/openssl-nseq.pod]=man1/openssl-nseq.pod.in
DEPEND[html/man1/openssl-ocsp.html]=man1/openssl-ocsp.pod
GENERATE[html/man1/openssl-ocsp.html]=man1/openssl-ocsp.pod
DEPEND[man/man1/openssl-ocsp.1]=man1/openssl-ocsp.pod
GENERATE[man/man1/openssl-ocsp.1]=man1/openssl-ocsp.pod
DEPEND[man1/openssl-ocsp.pod]{pod}=man1/openssl-ocsp.pod.in
GENERATE[man1/openssl-ocsp.pod]=man1/openssl-ocsp.pod.in
DEPEND[html/man1/openssl-passphrase-options.html]=man1/openssl-passphrase-options.pod
GENERATE[html/man1/openssl-passphrase-options.html]=man1/openssl-passphrase-options.pod
DEPEND[man/man1/openssl-passphrase-options.1]=man1/openssl-passphrase-options.pod
GENERATE[man/man1/openssl-passphrase-options.1]=man1/openssl-passphrase-options.pod
DEPEND[html/man1/openssl-passwd.html]=man1/openssl-passwd.pod
GENERATE[html/man1/openssl-passwd.html]=man1/openssl-passwd.pod
DEPEND[man/man1/openssl-passwd.1]=man1/openssl-passwd.pod
GENERATE[man/man1/openssl-passwd.1]=man1/openssl-passwd.pod
DEPEND[man1/openssl-passwd.pod]{pod}=man1/openssl-passwd.pod.in
GENERATE[man1/openssl-passwd.pod]=man1/openssl-passwd.pod.in
DEPEND[html/man1/openssl-pkcs12.html]=man1/openssl-pkcs12.pod
GENERATE[html/man1/openssl-pkcs12.html]=man1/openssl-pkcs12.pod
DEPEND[man/man1/openssl-pkcs12.1]=man1/openssl-pkcs12.pod
GENERATE[man/man1/openssl-pkcs12.1]=man1/openssl-pkcs12.pod
DEPEND[man1/openssl-pkcs12.pod]{pod}=man1/openssl-pkcs12.pod.in
GENERATE[man1/openssl-pkcs12.pod]=man1/openssl-pkcs12.pod.in
DEPEND[html/man1/openssl-pkcs7.html]=man1/openssl-pkcs7.pod
GENERATE[html/man1/openssl-pkcs7.html]=man1/openssl-pkcs7.pod
DEPEND[man/man1/openssl-pkcs7.1]=man1/openssl-pkcs7.pod
GENERATE[man/man1/openssl-pkcs7.1]=man1/openssl-pkcs7.pod
DEPEND[man1/openssl-pkcs7.pod]{pod}=man1/openssl-pkcs7.pod.in
GENERATE[man1/openssl-pkcs7.pod]=man1/openssl-pkcs7.pod.in
DEPEND[html/man1/openssl-pkcs8.html]=man1/openssl-pkcs8.pod
GENERATE[html/man1/openssl-pkcs8.html]=man1/openssl-pkcs8.pod
DEPEND[man/man1/openssl-pkcs8.1]=man1/openssl-pkcs8.pod
GENERATE[man/man1/openssl-pkcs8.1]=man1/openssl-pkcs8.pod
DEPEND[man1/openssl-pkcs8.pod]{pod}=man1/openssl-pkcs8.pod.in
GENERATE[man1/openssl-pkcs8.pod]=man1/openssl-pkcs8.pod.in
DEPEND[html/man1/openssl-pkey.html]=man1/openssl-pkey.pod
GENERATE[html/man1/openssl-pkey.html]=man1/openssl-pkey.pod
DEPEND[man/man1/openssl-pkey.1]=man1/openssl-pkey.pod
GENERATE[man/man1/openssl-pkey.1]=man1/openssl-pkey.pod
DEPEND[man1/openssl-pkey.pod]{pod}=man1/openssl-pkey.pod.in
GENERATE[man1/openssl-pkey.pod]=man1/openssl-pkey.pod.in
DEPEND[html/man1/openssl-pkeyparam.html]=man1/openssl-pkeyparam.pod
GENERATE[html/man1/openssl-pkeyparam.html]=man1/openssl-pkeyparam.pod
DEPEND[man/man1/openssl-pkeyparam.1]=man1/openssl-pkeyparam.pod
GENERATE[man/man1/openssl-pkeyparam.1]=man1/openssl-pkeyparam.pod
DEPEND[man1/openssl-pkeyparam.pod]{pod}=man1/openssl-pkeyparam.pod.in
GENERATE[man1/openssl-pkeyparam.pod]=man1/openssl-pkeyparam.pod.in
DEPEND[html/man1/openssl-pkeyutl.html]=man1/openssl-pkeyutl.pod
GENERATE[html/man1/openssl-pkeyutl.html]=man1/openssl-pkeyutl.pod
DEPEND[man/man1/openssl-pkeyutl.1]=man1/openssl-pkeyutl.pod
GENERATE[man/man1/openssl-pkeyutl.1]=man1/openssl-pkeyutl.pod
DEPEND[man1/openssl-pkeyutl.pod]{pod}=man1/openssl-pkeyutl.pod.in
GENERATE[man1/openssl-pkeyutl.pod]=man1/openssl-pkeyutl.pod.in
DEPEND[html/man1/openssl-prime.html]=man1/openssl-prime.pod
GENERATE[html/man1/openssl-prime.html]=man1/openssl-prime.pod
DEPEND[man/man1/openssl-prime.1]=man1/openssl-prime.pod
GENERATE[man/man1/openssl-prime.1]=man1/openssl-prime.pod
DEPEND[man1/openssl-prime.pod]{pod}=man1/openssl-prime.pod.in
GENERATE[man1/openssl-prime.pod]=man1/openssl-prime.pod.in
DEPEND[html/man1/openssl-rand.html]=man1/openssl-rand.pod
GENERATE[html/man1/openssl-rand.html]=man1/openssl-rand.pod
DEPEND[man/man1/openssl-rand.1]=man1/openssl-rand.pod
GENERATE[man/man1/openssl-rand.1]=man1/openssl-rand.pod
DEPEND[man1/openssl-rand.pod]{pod}=man1/openssl-rand.pod.in
GENERATE[man1/openssl-rand.pod]=man1/openssl-rand.pod.in
DEPEND[html/man1/openssl-rehash.html]=man1/openssl-rehash.pod
GENERATE[html/man1/openssl-rehash.html]=man1/openssl-rehash.pod
DEPEND[man/man1/openssl-rehash.1]=man1/openssl-rehash.pod
GENERATE[man/man1/openssl-rehash.1]=man1/openssl-rehash.pod
DEPEND[man1/openssl-rehash.pod]{pod}=man1/openssl-rehash.pod.in
GENERATE[man1/openssl-rehash.pod]=man1/openssl-rehash.pod.in
DEPEND[html/man1/openssl-req.html]=man1/openssl-req.pod
GENERATE[html/man1/openssl-req.html]=man1/openssl-req.pod
DEPEND[man/man1/openssl-req.1]=man1/openssl-req.pod
GENERATE[man/man1/openssl-req.1]=man1/openssl-req.pod
DEPEND[man1/openssl-req.pod]{pod}=man1/openssl-req.pod.in
GENERATE[man1/openssl-req.pod]=man1/openssl-req.pod.in
DEPEND[html/man1/openssl-rsa.html]=man1/openssl-rsa.pod
GENERATE[html/man1/openssl-rsa.html]=man1/openssl-rsa.pod
DEPEND[man/man1/openssl-rsa.1]=man1/openssl-rsa.pod
GENERATE[man/man1/openssl-rsa.1]=man1/openssl-rsa.pod
DEPEND[man1/openssl-rsa.pod]{pod}=man1/openssl-rsa.pod.in
GENERATE[man1/openssl-rsa.pod]=man1/openssl-rsa.pod.in
DEPEND[html/man1/openssl-rsautl.html]=man1/openssl-rsautl.pod
GENERATE[html/man1/openssl-rsautl.html]=man1/openssl-rsautl.pod
DEPEND[man/man1/openssl-rsautl.1]=man1/openssl-rsautl.pod
GENERATE[man/man1/openssl-rsautl.1]=man1/openssl-rsautl.pod
DEPEND[man1/openssl-rsautl.pod]{pod}=man1/openssl-rsautl.pod.in
GENERATE[man1/openssl-rsautl.pod]=man1/openssl-rsautl.pod.in
DEPEND[html/man1/openssl-s_client.html]=man1/openssl-s_client.pod
GENERATE[html/man1/openssl-s_client.html]=man1/openssl-s_client.pod
DEPEND[man/man1/openssl-s_client.1]=man1/openssl-s_client.pod
GENERATE[man/man1/openssl-s_client.1]=man1/openssl-s_client.pod
DEPEND[man1/openssl-s_client.pod]{pod}=man1/openssl-s_client.pod.in
GENERATE[man1/openssl-s_client.pod]=man1/openssl-s_client.pod.in
DEPEND[html/man1/openssl-s_server.html]=man1/openssl-s_server.pod
GENERATE[html/man1/openssl-s_server.html]=man1/openssl-s_server.pod
DEPEND[man/man1/openssl-s_server.1]=man1/openssl-s_server.pod
GENERATE[man/man1/openssl-s_server.1]=man1/openssl-s_server.pod
DEPEND[man1/openssl-s_server.pod]{pod}=man1/openssl-s_server.pod.in
GENERATE[man1/openssl-s_server.pod]=man1/openssl-s_server.pod.in
DEPEND[html/man1/openssl-s_time.html]=man1/openssl-s_time.pod
GENERATE[html/man1/openssl-s_time.html]=man1/openssl-s_time.pod
DEPEND[man/man1/openssl-s_time.1]=man1/openssl-s_time.pod
GENERATE[man/man1/openssl-s_time.1]=man1/openssl-s_time.pod
DEPEND[man1/openssl-s_time.pod]{pod}=man1/openssl-s_time.pod.in
GENERATE[man1/openssl-s_time.pod]=man1/openssl-s_time.pod.in
DEPEND[html/man1/openssl-sess_id.html]=man1/openssl-sess_id.pod
GENERATE[html/man1/openssl-sess_id.html]=man1/openssl-sess_id.pod
DEPEND[man/man1/openssl-sess_id.1]=man1/openssl-sess_id.pod
GENERATE[man/man1/openssl-sess_id.1]=man1/openssl-sess_id.pod
DEPEND[man1/openssl-sess_id.pod]{pod}=man1/openssl-sess_id.pod.in
GENERATE[man1/openssl-sess_id.pod]=man1/openssl-sess_id.pod.in
DEPEND[html/man1/openssl-smime.html]=man1/openssl-smime.pod
GENERATE[html/man1/openssl-smime.html]=man1/openssl-smime.pod
DEPEND[man/man1/openssl-smime.1]=man1/openssl-smime.pod
GENERATE[man/man1/openssl-smime.1]=man1/openssl-smime.pod
DEPEND[man1/openssl-smime.pod]{pod}=man1/openssl-smime.pod.in
GENERATE[man1/openssl-smime.pod]=man1/openssl-smime.pod.in
DEPEND[html/man1/openssl-speed.html]=man1/openssl-speed.pod
GENERATE[html/man1/openssl-speed.html]=man1/openssl-speed.pod
DEPEND[man/man1/openssl-speed.1]=man1/openssl-speed.pod
GENERATE[man/man1/openssl-speed.1]=man1/openssl-speed.pod
DEPEND[man1/openssl-speed.pod]{pod}=man1/openssl-speed.pod.in
GENERATE[man1/openssl-speed.pod]=man1/openssl-speed.pod.in
DEPEND[html/man1/openssl-spkac.html]=man1/openssl-spkac.pod
GENERATE[html/man1/openssl-spkac.html]=man1/openssl-spkac.pod
DEPEND[man/man1/openssl-spkac.1]=man1/openssl-spkac.pod
GENERATE[man/man1/openssl-spkac.1]=man1/openssl-spkac.pod
DEPEND[man1/openssl-spkac.pod]{pod}=man1/openssl-spkac.pod.in
GENERATE[man1/openssl-spkac.pod]=man1/openssl-spkac.pod.in
DEPEND[html/man1/openssl-srp.html]=man1/openssl-srp.pod
GENERATE[html/man1/openssl-srp.html]=man1/openssl-srp.pod
DEPEND[man/man1/openssl-srp.1]=man1/openssl-srp.pod
GENERATE[man/man1/openssl-srp.1]=man1/openssl-srp.pod
DEPEND[man1/openssl-srp.pod]{pod}=man1/openssl-srp.pod.in
GENERATE[man1/openssl-srp.pod]=man1/openssl-srp.pod.in
DEPEND[html/man1/openssl-storeutl.html]=man1/openssl-storeutl.pod
GENERATE[html/man1/openssl-storeutl.html]=man1/openssl-storeutl.pod
DEPEND[man/man1/openssl-storeutl.1]=man1/openssl-storeutl.pod
GENERATE[man/man1/openssl-storeutl.1]=man1/openssl-storeutl.pod
DEPEND[man1/openssl-storeutl.pod]{pod}=man1/openssl-storeutl.pod.in
GENERATE[man1/openssl-storeutl.pod]=man1/openssl-storeutl.pod.in
DEPEND[html/man1/openssl-ts.html]=man1/openssl-ts.pod
GENERATE[html/man1/openssl-ts.html]=man1/openssl-ts.pod
DEPEND[man/man1/openssl-ts.1]=man1/openssl-ts.pod
GENERATE[man/man1/openssl-ts.1]=man1/openssl-ts.pod
DEPEND[man1/openssl-ts.pod]{pod}=man1/openssl-ts.pod.in
GENERATE[man1/openssl-ts.pod]=man1/openssl-ts.pod.in
DEPEND[html/man1/openssl-verification-options.html]=man1/openssl-verification-options.pod
GENERATE[html/man1/openssl-verification-options.html]=man1/openssl-verification-options.pod
DEPEND[man/man1/openssl-verification-options.1]=man1/openssl-verification-options.pod
GENERATE[man/man1/openssl-verification-options.1]=man1/openssl-verification-options.pod
DEPEND[html/man1/openssl-verify.html]=man1/openssl-verify.pod
GENERATE[html/man1/openssl-verify.html]=man1/openssl-verify.pod
DEPEND[man/man1/openssl-verify.1]=man1/openssl-verify.pod
GENERATE[man/man1/openssl-verify.1]=man1/openssl-verify.pod
DEPEND[man1/openssl-verify.pod]{pod}=man1/openssl-verify.pod.in
GENERATE[man1/openssl-verify.pod]=man1/openssl-verify.pod.in
DEPEND[html/man1/openssl-version.html]=man1/openssl-version.pod
GENERATE[html/man1/openssl-version.html]=man1/openssl-version.pod
DEPEND[man/man1/openssl-version.1]=man1/openssl-version.pod
GENERATE[man/man1/openssl-version.1]=man1/openssl-version.pod
DEPEND[man1/openssl-version.pod]{pod}=man1/openssl-version.pod.in
GENERATE[man1/openssl-version.pod]=man1/openssl-version.pod.in
DEPEND[html/man1/openssl-x509.html]=man1/openssl-x509.pod
GENERATE[html/man1/openssl-x509.html]=man1/openssl-x509.pod
DEPEND[man/man1/openssl-x509.1]=man1/openssl-x509.pod
GENERATE[man/man1/openssl-x509.1]=man1/openssl-x509.pod
DEPEND[man1/openssl-x509.pod]{pod}=man1/openssl-x509.pod.in
GENERATE[man1/openssl-x509.pod]=man1/openssl-x509.pod.in
DEPEND[html/man1/openssl.html]=man1/openssl.pod
GENERATE[html/man1/openssl.html]=man1/openssl.pod
DEPEND[man/man1/openssl.1]=man1/openssl.pod
GENERATE[man/man1/openssl.1]=man1/openssl.pod
DEPEND[html/man1/tsget.html]=man1/tsget.pod
GENERATE[html/man1/tsget.html]=man1/tsget.pod
DEPEND[man/man1/tsget.1]=man1/tsget.pod
GENERATE[man/man1/tsget.1]=man1/tsget.pod
IMAGEDOCS[man1]=
HTMLDOCS[man1]=html/man1/CA.pl.html \
html/man1/openssl-asn1parse.html \
html/man1/openssl-ca.html \
html/man1/openssl-ciphers.html \
html/man1/openssl-cmds.html \
html/man1/openssl-cmp.html \
html/man1/openssl-cms.html \
html/man1/openssl-crl.html \
html/man1/openssl-crl2pkcs7.html \
html/man1/openssl-dgst.html \
html/man1/openssl-dhparam.html \
html/man1/openssl-dsa.html \
html/man1/openssl-dsaparam.html \
html/man1/openssl-ec.html \
html/man1/openssl-ecparam.html \
html/man1/openssl-enc.html \
html/man1/openssl-engine.html \
html/man1/openssl-errstr.html \
html/man1/openssl-fipsinstall.html \
html/man1/openssl-format-options.html \
html/man1/openssl-gendsa.html \
html/man1/openssl-genpkey.html \
html/man1/openssl-genrsa.html \
html/man1/openssl-info.html \
html/man1/openssl-kdf.html \
html/man1/openssl-list.html \
html/man1/openssl-mac.html \
html/man1/openssl-namedisplay-options.html \
html/man1/openssl-nseq.html \
html/man1/openssl-ocsp.html \
html/man1/openssl-passphrase-options.html \
html/man1/openssl-passwd.html \
html/man1/openssl-pkcs12.html \
html/man1/openssl-pkcs7.html \
html/man1/openssl-pkcs8.html \
html/man1/openssl-pkey.html \
html/man1/openssl-pkeyparam.html \
html/man1/openssl-pkeyutl.html \
html/man1/openssl-prime.html \
html/man1/openssl-rand.html \
html/man1/openssl-rehash.html \
html/man1/openssl-req.html \
html/man1/openssl-rsa.html \
html/man1/openssl-rsautl.html \
html/man1/openssl-s_client.html \
html/man1/openssl-s_server.html \
html/man1/openssl-s_time.html \
html/man1/openssl-sess_id.html \
html/man1/openssl-smime.html \
html/man1/openssl-speed.html \
html/man1/openssl-spkac.html \
html/man1/openssl-srp.html \
html/man1/openssl-storeutl.html \
html/man1/openssl-ts.html \
html/man1/openssl-verification-options.html \
html/man1/openssl-verify.html \
html/man1/openssl-version.html \
html/man1/openssl-x509.html \
html/man1/openssl.html \
html/man1/tsget.html
MANDOCS[man1]=man/man1/CA.pl.1 \
man/man1/openssl-asn1parse.1 \
man/man1/openssl-ca.1 \
man/man1/openssl-ciphers.1 \
man/man1/openssl-cmds.1 \
man/man1/openssl-cmp.1 \
man/man1/openssl-cms.1 \
man/man1/openssl-crl.1 \
man/man1/openssl-crl2pkcs7.1 \
man/man1/openssl-dgst.1 \
man/man1/openssl-dhparam.1 \
man/man1/openssl-dsa.1 \
man/man1/openssl-dsaparam.1 \
man/man1/openssl-ec.1 \
man/man1/openssl-ecparam.1 \
man/man1/openssl-enc.1 \
man/man1/openssl-engine.1 \
man/man1/openssl-errstr.1 \
man/man1/openssl-fipsinstall.1 \
man/man1/openssl-format-options.1 \
man/man1/openssl-gendsa.1 \
man/man1/openssl-genpkey.1 \
man/man1/openssl-genrsa.1 \
man/man1/openssl-info.1 \
man/man1/openssl-kdf.1 \
man/man1/openssl-list.1 \
man/man1/openssl-mac.1 \
man/man1/openssl-namedisplay-options.1 \
man/man1/openssl-nseq.1 \
man/man1/openssl-ocsp.1 \
man/man1/openssl-passphrase-options.1 \
man/man1/openssl-passwd.1 \
man/man1/openssl-pkcs12.1 \
man/man1/openssl-pkcs7.1 \
man/man1/openssl-pkcs8.1 \
man/man1/openssl-pkey.1 \
man/man1/openssl-pkeyparam.1 \
man/man1/openssl-pkeyutl.1 \
man/man1/openssl-prime.1 \
man/man1/openssl-rand.1 \
man/man1/openssl-rehash.1 \
man/man1/openssl-req.1 \
man/man1/openssl-rsa.1 \
man/man1/openssl-rsautl.1 \
man/man1/openssl-s_client.1 \
man/man1/openssl-s_server.1 \
man/man1/openssl-s_time.1 \
man/man1/openssl-sess_id.1 \
man/man1/openssl-smime.1 \
man/man1/openssl-speed.1 \
man/man1/openssl-spkac.1 \
man/man1/openssl-srp.1 \
man/man1/openssl-storeutl.1 \
man/man1/openssl-ts.1 \
man/man1/openssl-verification-options.1 \
man/man1/openssl-verify.1 \
man/man1/openssl-version.1 \
man/man1/openssl-x509.1 \
man/man1/openssl.1 \
man/man1/tsget.1
DEPEND[html/man3/ADMISSIONS.html]=man3/ADMISSIONS.pod
GENERATE[html/man3/ADMISSIONS.html]=man3/ADMISSIONS.pod
DEPEND[man/man3/ADMISSIONS.3]=man3/ADMISSIONS.pod
GENERATE[man/man3/ADMISSIONS.3]=man3/ADMISSIONS.pod
DEPEND[html/man3/ASN1_EXTERN_FUNCS.html]=man3/ASN1_EXTERN_FUNCS.pod
GENERATE[html/man3/ASN1_EXTERN_FUNCS.html]=man3/ASN1_EXTERN_FUNCS.pod
DEPEND[man/man3/ASN1_EXTERN_FUNCS.3]=man3/ASN1_EXTERN_FUNCS.pod
GENERATE[man/man3/ASN1_EXTERN_FUNCS.3]=man3/ASN1_EXTERN_FUNCS.pod
DEPEND[html/man3/ASN1_INTEGER_get_int64.html]=man3/ASN1_INTEGER_get_int64.pod
GENERATE[html/man3/ASN1_INTEGER_get_int64.html]=man3/ASN1_INTEGER_get_int64.pod
DEPEND[man/man3/ASN1_INTEGER_get_int64.3]=man3/ASN1_INTEGER_get_int64.pod
GENERATE[man/man3/ASN1_INTEGER_get_int64.3]=man3/ASN1_INTEGER_get_int64.pod
DEPEND[html/man3/ASN1_INTEGER_new.html]=man3/ASN1_INTEGER_new.pod
GENERATE[html/man3/ASN1_INTEGER_new.html]=man3/ASN1_INTEGER_new.pod
DEPEND[man/man3/ASN1_INTEGER_new.3]=man3/ASN1_INTEGER_new.pod
GENERATE[man/man3/ASN1_INTEGER_new.3]=man3/ASN1_INTEGER_new.pod
DEPEND[html/man3/ASN1_ITEM_lookup.html]=man3/ASN1_ITEM_lookup.pod
GENERATE[html/man3/ASN1_ITEM_lookup.html]=man3/ASN1_ITEM_lookup.pod
DEPEND[man/man3/ASN1_ITEM_lookup.3]=man3/ASN1_ITEM_lookup.pod
GENERATE[man/man3/ASN1_ITEM_lookup.3]=man3/ASN1_ITEM_lookup.pod
DEPEND[html/man3/ASN1_OBJECT_new.html]=man3/ASN1_OBJECT_new.pod
GENERATE[html/man3/ASN1_OBJECT_new.html]=man3/ASN1_OBJECT_new.pod
DEPEND[man/man3/ASN1_OBJECT_new.3]=man3/ASN1_OBJECT_new.pod
GENERATE[man/man3/ASN1_OBJECT_new.3]=man3/ASN1_OBJECT_new.pod
DEPEND[html/man3/ASN1_STRING_TABLE_add.html]=man3/ASN1_STRING_TABLE_add.pod
GENERATE[html/man3/ASN1_STRING_TABLE_add.html]=man3/ASN1_STRING_TABLE_add.pod
DEPEND[man/man3/ASN1_STRING_TABLE_add.3]=man3/ASN1_STRING_TABLE_add.pod
GENERATE[man/man3/ASN1_STRING_TABLE_add.3]=man3/ASN1_STRING_TABLE_add.pod
DEPEND[html/man3/ASN1_STRING_length.html]=man3/ASN1_STRING_length.pod
GENERATE[html/man3/ASN1_STRING_length.html]=man3/ASN1_STRING_length.pod
DEPEND[man/man3/ASN1_STRING_length.3]=man3/ASN1_STRING_length.pod
GENERATE[man/man3/ASN1_STRING_length.3]=man3/ASN1_STRING_length.pod
DEPEND[html/man3/ASN1_STRING_new.html]=man3/ASN1_STRING_new.pod
GENERATE[html/man3/ASN1_STRING_new.html]=man3/ASN1_STRING_new.pod
DEPEND[man/man3/ASN1_STRING_new.3]=man3/ASN1_STRING_new.pod
GENERATE[man/man3/ASN1_STRING_new.3]=man3/ASN1_STRING_new.pod
DEPEND[html/man3/ASN1_STRING_print_ex.html]=man3/ASN1_STRING_print_ex.pod
GENERATE[html/man3/ASN1_STRING_print_ex.html]=man3/ASN1_STRING_print_ex.pod
DEPEND[man/man3/ASN1_STRING_print_ex.3]=man3/ASN1_STRING_print_ex.pod
GENERATE[man/man3/ASN1_STRING_print_ex.3]=man3/ASN1_STRING_print_ex.pod
DEPEND[html/man3/ASN1_TIME_set.html]=man3/ASN1_TIME_set.pod
GENERATE[html/man3/ASN1_TIME_set.html]=man3/ASN1_TIME_set.pod
DEPEND[man/man3/ASN1_TIME_set.3]=man3/ASN1_TIME_set.pod
GENERATE[man/man3/ASN1_TIME_set.3]=man3/ASN1_TIME_set.pod
DEPEND[html/man3/ASN1_TYPE_get.html]=man3/ASN1_TYPE_get.pod
GENERATE[html/man3/ASN1_TYPE_get.html]=man3/ASN1_TYPE_get.pod
DEPEND[man/man3/ASN1_TYPE_get.3]=man3/ASN1_TYPE_get.pod
GENERATE[man/man3/ASN1_TYPE_get.3]=man3/ASN1_TYPE_get.pod
DEPEND[html/man3/ASN1_aux_cb.html]=man3/ASN1_aux_cb.pod
GENERATE[html/man3/ASN1_aux_cb.html]=man3/ASN1_aux_cb.pod
DEPEND[man/man3/ASN1_aux_cb.3]=man3/ASN1_aux_cb.pod
GENERATE[man/man3/ASN1_aux_cb.3]=man3/ASN1_aux_cb.pod
DEPEND[html/man3/ASN1_generate_nconf.html]=man3/ASN1_generate_nconf.pod
GENERATE[html/man3/ASN1_generate_nconf.html]=man3/ASN1_generate_nconf.pod
DEPEND[man/man3/ASN1_generate_nconf.3]=man3/ASN1_generate_nconf.pod
GENERATE[man/man3/ASN1_generate_nconf.3]=man3/ASN1_generate_nconf.pod
DEPEND[html/man3/ASN1_item_d2i_bio.html]=man3/ASN1_item_d2i_bio.pod
GENERATE[html/man3/ASN1_item_d2i_bio.html]=man3/ASN1_item_d2i_bio.pod
DEPEND[man/man3/ASN1_item_d2i_bio.3]=man3/ASN1_item_d2i_bio.pod
GENERATE[man/man3/ASN1_item_d2i_bio.3]=man3/ASN1_item_d2i_bio.pod
DEPEND[html/man3/ASN1_item_new.html]=man3/ASN1_item_new.pod
GENERATE[html/man3/ASN1_item_new.html]=man3/ASN1_item_new.pod
DEPEND[man/man3/ASN1_item_new.3]=man3/ASN1_item_new.pod
GENERATE[man/man3/ASN1_item_new.3]=man3/ASN1_item_new.pod
DEPEND[html/man3/ASN1_item_sign.html]=man3/ASN1_item_sign.pod
GENERATE[html/man3/ASN1_item_sign.html]=man3/ASN1_item_sign.pod
DEPEND[man/man3/ASN1_item_sign.3]=man3/ASN1_item_sign.pod
GENERATE[man/man3/ASN1_item_sign.3]=man3/ASN1_item_sign.pod
DEPEND[html/man3/ASYNC_WAIT_CTX_new.html]=man3/ASYNC_WAIT_CTX_new.pod
GENERATE[html/man3/ASYNC_WAIT_CTX_new.html]=man3/ASYNC_WAIT_CTX_new.pod
DEPEND[man/man3/ASYNC_WAIT_CTX_new.3]=man3/ASYNC_WAIT_CTX_new.pod
GENERATE[man/man3/ASYNC_WAIT_CTX_new.3]=man3/ASYNC_WAIT_CTX_new.pod
DEPEND[html/man3/ASYNC_start_job.html]=man3/ASYNC_start_job.pod
GENERATE[html/man3/ASYNC_start_job.html]=man3/ASYNC_start_job.pod
DEPEND[man/man3/ASYNC_start_job.3]=man3/ASYNC_start_job.pod
GENERATE[man/man3/ASYNC_start_job.3]=man3/ASYNC_start_job.pod
DEPEND[html/man3/BF_encrypt.html]=man3/BF_encrypt.pod
GENERATE[html/man3/BF_encrypt.html]=man3/BF_encrypt.pod
DEPEND[man/man3/BF_encrypt.3]=man3/BF_encrypt.pod
GENERATE[man/man3/BF_encrypt.3]=man3/BF_encrypt.pod
DEPEND[html/man3/BIO_ADDR.html]=man3/BIO_ADDR.pod
GENERATE[html/man3/BIO_ADDR.html]=man3/BIO_ADDR.pod
DEPEND[man/man3/BIO_ADDR.3]=man3/BIO_ADDR.pod
GENERATE[man/man3/BIO_ADDR.3]=man3/BIO_ADDR.pod
DEPEND[html/man3/BIO_ADDRINFO.html]=man3/BIO_ADDRINFO.pod
GENERATE[html/man3/BIO_ADDRINFO.html]=man3/BIO_ADDRINFO.pod
DEPEND[man/man3/BIO_ADDRINFO.3]=man3/BIO_ADDRINFO.pod
GENERATE[man/man3/BIO_ADDRINFO.3]=man3/BIO_ADDRINFO.pod
DEPEND[html/man3/BIO_connect.html]=man3/BIO_connect.pod
GENERATE[html/man3/BIO_connect.html]=man3/BIO_connect.pod
DEPEND[man/man3/BIO_connect.3]=man3/BIO_connect.pod
GENERATE[man/man3/BIO_connect.3]=man3/BIO_connect.pod
DEPEND[html/man3/BIO_ctrl.html]=man3/BIO_ctrl.pod
GENERATE[html/man3/BIO_ctrl.html]=man3/BIO_ctrl.pod
DEPEND[man/man3/BIO_ctrl.3]=man3/BIO_ctrl.pod
GENERATE[man/man3/BIO_ctrl.3]=man3/BIO_ctrl.pod
DEPEND[html/man3/BIO_f_base64.html]=man3/BIO_f_base64.pod
GENERATE[html/man3/BIO_f_base64.html]=man3/BIO_f_base64.pod
DEPEND[man/man3/BIO_f_base64.3]=man3/BIO_f_base64.pod
GENERATE[man/man3/BIO_f_base64.3]=man3/BIO_f_base64.pod
DEPEND[html/man3/BIO_f_buffer.html]=man3/BIO_f_buffer.pod
GENERATE[html/man3/BIO_f_buffer.html]=man3/BIO_f_buffer.pod
DEPEND[man/man3/BIO_f_buffer.3]=man3/BIO_f_buffer.pod
GENERATE[man/man3/BIO_f_buffer.3]=man3/BIO_f_buffer.pod
DEPEND[html/man3/BIO_f_cipher.html]=man3/BIO_f_cipher.pod
GENERATE[html/man3/BIO_f_cipher.html]=man3/BIO_f_cipher.pod
DEPEND[man/man3/BIO_f_cipher.3]=man3/BIO_f_cipher.pod
GENERATE[man/man3/BIO_f_cipher.3]=man3/BIO_f_cipher.pod
DEPEND[html/man3/BIO_f_md.html]=man3/BIO_f_md.pod
GENERATE[html/man3/BIO_f_md.html]=man3/BIO_f_md.pod
DEPEND[man/man3/BIO_f_md.3]=man3/BIO_f_md.pod
GENERATE[man/man3/BIO_f_md.3]=man3/BIO_f_md.pod
DEPEND[html/man3/BIO_f_null.html]=man3/BIO_f_null.pod
GENERATE[html/man3/BIO_f_null.html]=man3/BIO_f_null.pod
DEPEND[man/man3/BIO_f_null.3]=man3/BIO_f_null.pod
GENERATE[man/man3/BIO_f_null.3]=man3/BIO_f_null.pod
DEPEND[html/man3/BIO_f_prefix.html]=man3/BIO_f_prefix.pod
GENERATE[html/man3/BIO_f_prefix.html]=man3/BIO_f_prefix.pod
DEPEND[man/man3/BIO_f_prefix.3]=man3/BIO_f_prefix.pod
GENERATE[man/man3/BIO_f_prefix.3]=man3/BIO_f_prefix.pod
DEPEND[html/man3/BIO_f_readbuffer.html]=man3/BIO_f_readbuffer.pod
GENERATE[html/man3/BIO_f_readbuffer.html]=man3/BIO_f_readbuffer.pod
DEPEND[man/man3/BIO_f_readbuffer.3]=man3/BIO_f_readbuffer.pod
GENERATE[man/man3/BIO_f_readbuffer.3]=man3/BIO_f_readbuffer.pod
DEPEND[html/man3/BIO_f_ssl.html]=man3/BIO_f_ssl.pod
GENERATE[html/man3/BIO_f_ssl.html]=man3/BIO_f_ssl.pod
DEPEND[man/man3/BIO_f_ssl.3]=man3/BIO_f_ssl.pod
GENERATE[man/man3/BIO_f_ssl.3]=man3/BIO_f_ssl.pod
DEPEND[html/man3/BIO_find_type.html]=man3/BIO_find_type.pod
GENERATE[html/man3/BIO_find_type.html]=man3/BIO_find_type.pod
DEPEND[man/man3/BIO_find_type.3]=man3/BIO_find_type.pod
GENERATE[man/man3/BIO_find_type.3]=man3/BIO_find_type.pod
DEPEND[html/man3/BIO_get_data.html]=man3/BIO_get_data.pod
GENERATE[html/man3/BIO_get_data.html]=man3/BIO_get_data.pod
DEPEND[man/man3/BIO_get_data.3]=man3/BIO_get_data.pod
GENERATE[man/man3/BIO_get_data.3]=man3/BIO_get_data.pod
DEPEND[html/man3/BIO_get_ex_new_index.html]=man3/BIO_get_ex_new_index.pod
GENERATE[html/man3/BIO_get_ex_new_index.html]=man3/BIO_get_ex_new_index.pod
DEPEND[man/man3/BIO_get_ex_new_index.3]=man3/BIO_get_ex_new_index.pod
GENERATE[man/man3/BIO_get_ex_new_index.3]=man3/BIO_get_ex_new_index.pod
DEPEND[html/man3/BIO_meth_new.html]=man3/BIO_meth_new.pod
GENERATE[html/man3/BIO_meth_new.html]=man3/BIO_meth_new.pod
DEPEND[man/man3/BIO_meth_new.3]=man3/BIO_meth_new.pod
GENERATE[man/man3/BIO_meth_new.3]=man3/BIO_meth_new.pod
DEPEND[html/man3/BIO_new.html]=man3/BIO_new.pod
GENERATE[html/man3/BIO_new.html]=man3/BIO_new.pod
DEPEND[man/man3/BIO_new.3]=man3/BIO_new.pod
GENERATE[man/man3/BIO_new.3]=man3/BIO_new.pod
DEPEND[html/man3/BIO_new_CMS.html]=man3/BIO_new_CMS.pod
GENERATE[html/man3/BIO_new_CMS.html]=man3/BIO_new_CMS.pod
DEPEND[man/man3/BIO_new_CMS.3]=man3/BIO_new_CMS.pod
GENERATE[man/man3/BIO_new_CMS.3]=man3/BIO_new_CMS.pod
DEPEND[html/man3/BIO_parse_hostserv.html]=man3/BIO_parse_hostserv.pod
GENERATE[html/man3/BIO_parse_hostserv.html]=man3/BIO_parse_hostserv.pod
DEPEND[man/man3/BIO_parse_hostserv.3]=man3/BIO_parse_hostserv.pod
GENERATE[man/man3/BIO_parse_hostserv.3]=man3/BIO_parse_hostserv.pod
DEPEND[html/man3/BIO_printf.html]=man3/BIO_printf.pod
GENERATE[html/man3/BIO_printf.html]=man3/BIO_printf.pod
DEPEND[man/man3/BIO_printf.3]=man3/BIO_printf.pod
GENERATE[man/man3/BIO_printf.3]=man3/BIO_printf.pod
DEPEND[html/man3/BIO_push.html]=man3/BIO_push.pod
GENERATE[html/man3/BIO_push.html]=man3/BIO_push.pod
DEPEND[man/man3/BIO_push.3]=man3/BIO_push.pod
GENERATE[man/man3/BIO_push.3]=man3/BIO_push.pod
DEPEND[html/man3/BIO_read.html]=man3/BIO_read.pod
GENERATE[html/man3/BIO_read.html]=man3/BIO_read.pod
DEPEND[man/man3/BIO_read.3]=man3/BIO_read.pod
GENERATE[man/man3/BIO_read.3]=man3/BIO_read.pod
DEPEND[html/man3/BIO_s_accept.html]=man3/BIO_s_accept.pod
GENERATE[html/man3/BIO_s_accept.html]=man3/BIO_s_accept.pod
DEPEND[man/man3/BIO_s_accept.3]=man3/BIO_s_accept.pod
GENERATE[man/man3/BIO_s_accept.3]=man3/BIO_s_accept.pod
DEPEND[html/man3/BIO_s_bio.html]=man3/BIO_s_bio.pod
GENERATE[html/man3/BIO_s_bio.html]=man3/BIO_s_bio.pod
DEPEND[man/man3/BIO_s_bio.3]=man3/BIO_s_bio.pod
GENERATE[man/man3/BIO_s_bio.3]=man3/BIO_s_bio.pod
DEPEND[html/man3/BIO_s_connect.html]=man3/BIO_s_connect.pod
GENERATE[html/man3/BIO_s_connect.html]=man3/BIO_s_connect.pod
DEPEND[man/man3/BIO_s_connect.3]=man3/BIO_s_connect.pod
GENERATE[man/man3/BIO_s_connect.3]=man3/BIO_s_connect.pod
DEPEND[html/man3/BIO_s_core.html]=man3/BIO_s_core.pod
GENERATE[html/man3/BIO_s_core.html]=man3/BIO_s_core.pod
DEPEND[man/man3/BIO_s_core.3]=man3/BIO_s_core.pod
GENERATE[man/man3/BIO_s_core.3]=man3/BIO_s_core.pod
DEPEND[html/man3/BIO_s_datagram.html]=man3/BIO_s_datagram.pod
GENERATE[html/man3/BIO_s_datagram.html]=man3/BIO_s_datagram.pod
DEPEND[man/man3/BIO_s_datagram.3]=man3/BIO_s_datagram.pod
GENERATE[man/man3/BIO_s_datagram.3]=man3/BIO_s_datagram.pod
DEPEND[html/man3/BIO_s_fd.html]=man3/BIO_s_fd.pod
GENERATE[html/man3/BIO_s_fd.html]=man3/BIO_s_fd.pod
DEPEND[man/man3/BIO_s_fd.3]=man3/BIO_s_fd.pod
GENERATE[man/man3/BIO_s_fd.3]=man3/BIO_s_fd.pod
DEPEND[html/man3/BIO_s_file.html]=man3/BIO_s_file.pod
GENERATE[html/man3/BIO_s_file.html]=man3/BIO_s_file.pod
DEPEND[man/man3/BIO_s_file.3]=man3/BIO_s_file.pod
GENERATE[man/man3/BIO_s_file.3]=man3/BIO_s_file.pod
DEPEND[html/man3/BIO_s_mem.html]=man3/BIO_s_mem.pod
GENERATE[html/man3/BIO_s_mem.html]=man3/BIO_s_mem.pod
DEPEND[man/man3/BIO_s_mem.3]=man3/BIO_s_mem.pod
GENERATE[man/man3/BIO_s_mem.3]=man3/BIO_s_mem.pod
DEPEND[html/man3/BIO_s_null.html]=man3/BIO_s_null.pod
GENERATE[html/man3/BIO_s_null.html]=man3/BIO_s_null.pod
DEPEND[man/man3/BIO_s_null.3]=man3/BIO_s_null.pod
GENERATE[man/man3/BIO_s_null.3]=man3/BIO_s_null.pod
DEPEND[html/man3/BIO_s_socket.html]=man3/BIO_s_socket.pod
GENERATE[html/man3/BIO_s_socket.html]=man3/BIO_s_socket.pod
DEPEND[man/man3/BIO_s_socket.3]=man3/BIO_s_socket.pod
GENERATE[man/man3/BIO_s_socket.3]=man3/BIO_s_socket.pod
DEPEND[html/man3/BIO_set_callback.html]=man3/BIO_set_callback.pod
GENERATE[html/man3/BIO_set_callback.html]=man3/BIO_set_callback.pod
DEPEND[man/man3/BIO_set_callback.3]=man3/BIO_set_callback.pod
GENERATE[man/man3/BIO_set_callback.3]=man3/BIO_set_callback.pod
DEPEND[html/man3/BIO_should_retry.html]=man3/BIO_should_retry.pod
GENERATE[html/man3/BIO_should_retry.html]=man3/BIO_should_retry.pod
DEPEND[man/man3/BIO_should_retry.3]=man3/BIO_should_retry.pod
GENERATE[man/man3/BIO_should_retry.3]=man3/BIO_should_retry.pod
DEPEND[html/man3/BIO_socket_wait.html]=man3/BIO_socket_wait.pod
GENERATE[html/man3/BIO_socket_wait.html]=man3/BIO_socket_wait.pod
DEPEND[man/man3/BIO_socket_wait.3]=man3/BIO_socket_wait.pod
GENERATE[man/man3/BIO_socket_wait.3]=man3/BIO_socket_wait.pod
DEPEND[html/man3/BN_BLINDING_new.html]=man3/BN_BLINDING_new.pod
GENERATE[html/man3/BN_BLINDING_new.html]=man3/BN_BLINDING_new.pod
DEPEND[man/man3/BN_BLINDING_new.3]=man3/BN_BLINDING_new.pod
GENERATE[man/man3/BN_BLINDING_new.3]=man3/BN_BLINDING_new.pod
DEPEND[html/man3/BN_CTX_new.html]=man3/BN_CTX_new.pod
GENERATE[html/man3/BN_CTX_new.html]=man3/BN_CTX_new.pod
DEPEND[man/man3/BN_CTX_new.3]=man3/BN_CTX_new.pod
GENERATE[man/man3/BN_CTX_new.3]=man3/BN_CTX_new.pod
DEPEND[html/man3/BN_CTX_start.html]=man3/BN_CTX_start.pod
GENERATE[html/man3/BN_CTX_start.html]=man3/BN_CTX_start.pod
DEPEND[man/man3/BN_CTX_start.3]=man3/BN_CTX_start.pod
GENERATE[man/man3/BN_CTX_start.3]=man3/BN_CTX_start.pod
DEPEND[html/man3/BN_add.html]=man3/BN_add.pod
GENERATE[html/man3/BN_add.html]=man3/BN_add.pod
DEPEND[man/man3/BN_add.3]=man3/BN_add.pod
GENERATE[man/man3/BN_add.3]=man3/BN_add.pod
DEPEND[html/man3/BN_add_word.html]=man3/BN_add_word.pod
GENERATE[html/man3/BN_add_word.html]=man3/BN_add_word.pod
DEPEND[man/man3/BN_add_word.3]=man3/BN_add_word.pod
GENERATE[man/man3/BN_add_word.3]=man3/BN_add_word.pod
DEPEND[html/man3/BN_bn2bin.html]=man3/BN_bn2bin.pod
GENERATE[html/man3/BN_bn2bin.html]=man3/BN_bn2bin.pod
DEPEND[man/man3/BN_bn2bin.3]=man3/BN_bn2bin.pod
GENERATE[man/man3/BN_bn2bin.3]=man3/BN_bn2bin.pod
DEPEND[html/man3/BN_cmp.html]=man3/BN_cmp.pod
GENERATE[html/man3/BN_cmp.html]=man3/BN_cmp.pod
DEPEND[man/man3/BN_cmp.3]=man3/BN_cmp.pod
GENERATE[man/man3/BN_cmp.3]=man3/BN_cmp.pod
DEPEND[html/man3/BN_copy.html]=man3/BN_copy.pod
GENERATE[html/man3/BN_copy.html]=man3/BN_copy.pod
DEPEND[man/man3/BN_copy.3]=man3/BN_copy.pod
GENERATE[man/man3/BN_copy.3]=man3/BN_copy.pod
DEPEND[html/man3/BN_generate_prime.html]=man3/BN_generate_prime.pod
GENERATE[html/man3/BN_generate_prime.html]=man3/BN_generate_prime.pod
DEPEND[man/man3/BN_generate_prime.3]=man3/BN_generate_prime.pod
GENERATE[man/man3/BN_generate_prime.3]=man3/BN_generate_prime.pod
DEPEND[html/man3/BN_mod_exp_mont.html]=man3/BN_mod_exp_mont.pod
GENERATE[html/man3/BN_mod_exp_mont.html]=man3/BN_mod_exp_mont.pod
DEPEND[man/man3/BN_mod_exp_mont.3]=man3/BN_mod_exp_mont.pod
GENERATE[man/man3/BN_mod_exp_mont.3]=man3/BN_mod_exp_mont.pod
DEPEND[html/man3/BN_mod_inverse.html]=man3/BN_mod_inverse.pod
GENERATE[html/man3/BN_mod_inverse.html]=man3/BN_mod_inverse.pod
DEPEND[man/man3/BN_mod_inverse.3]=man3/BN_mod_inverse.pod
GENERATE[man/man3/BN_mod_inverse.3]=man3/BN_mod_inverse.pod
DEPEND[html/man3/BN_mod_mul_montgomery.html]=man3/BN_mod_mul_montgomery.pod
GENERATE[html/man3/BN_mod_mul_montgomery.html]=man3/BN_mod_mul_montgomery.pod
DEPEND[man/man3/BN_mod_mul_montgomery.3]=man3/BN_mod_mul_montgomery.pod
GENERATE[man/man3/BN_mod_mul_montgomery.3]=man3/BN_mod_mul_montgomery.pod
DEPEND[html/man3/BN_mod_mul_reciprocal.html]=man3/BN_mod_mul_reciprocal.pod
GENERATE[html/man3/BN_mod_mul_reciprocal.html]=man3/BN_mod_mul_reciprocal.pod
DEPEND[man/man3/BN_mod_mul_reciprocal.3]=man3/BN_mod_mul_reciprocal.pod
GENERATE[man/man3/BN_mod_mul_reciprocal.3]=man3/BN_mod_mul_reciprocal.pod
DEPEND[html/man3/BN_new.html]=man3/BN_new.pod
GENERATE[html/man3/BN_new.html]=man3/BN_new.pod
DEPEND[man/man3/BN_new.3]=man3/BN_new.pod
GENERATE[man/man3/BN_new.3]=man3/BN_new.pod
DEPEND[html/man3/BN_num_bytes.html]=man3/BN_num_bytes.pod
GENERATE[html/man3/BN_num_bytes.html]=man3/BN_num_bytes.pod
DEPEND[man/man3/BN_num_bytes.3]=man3/BN_num_bytes.pod
GENERATE[man/man3/BN_num_bytes.3]=man3/BN_num_bytes.pod
DEPEND[html/man3/BN_rand.html]=man3/BN_rand.pod
GENERATE[html/man3/BN_rand.html]=man3/BN_rand.pod
DEPEND[man/man3/BN_rand.3]=man3/BN_rand.pod
GENERATE[man/man3/BN_rand.3]=man3/BN_rand.pod
DEPEND[html/man3/BN_security_bits.html]=man3/BN_security_bits.pod
GENERATE[html/man3/BN_security_bits.html]=man3/BN_security_bits.pod
DEPEND[man/man3/BN_security_bits.3]=man3/BN_security_bits.pod
GENERATE[man/man3/BN_security_bits.3]=man3/BN_security_bits.pod
DEPEND[html/man3/BN_set_bit.html]=man3/BN_set_bit.pod
GENERATE[html/man3/BN_set_bit.html]=man3/BN_set_bit.pod
DEPEND[man/man3/BN_set_bit.3]=man3/BN_set_bit.pod
GENERATE[man/man3/BN_set_bit.3]=man3/BN_set_bit.pod
DEPEND[html/man3/BN_swap.html]=man3/BN_swap.pod
GENERATE[html/man3/BN_swap.html]=man3/BN_swap.pod
DEPEND[man/man3/BN_swap.3]=man3/BN_swap.pod
GENERATE[man/man3/BN_swap.3]=man3/BN_swap.pod
DEPEND[html/man3/BN_zero.html]=man3/BN_zero.pod
GENERATE[html/man3/BN_zero.html]=man3/BN_zero.pod
DEPEND[man/man3/BN_zero.3]=man3/BN_zero.pod
GENERATE[man/man3/BN_zero.3]=man3/BN_zero.pod
DEPEND[html/man3/BUF_MEM_new.html]=man3/BUF_MEM_new.pod
GENERATE[html/man3/BUF_MEM_new.html]=man3/BUF_MEM_new.pod
DEPEND[man/man3/BUF_MEM_new.3]=man3/BUF_MEM_new.pod
GENERATE[man/man3/BUF_MEM_new.3]=man3/BUF_MEM_new.pod
DEPEND[html/man3/CMS_EncryptedData_decrypt.html]=man3/CMS_EncryptedData_decrypt.pod
GENERATE[html/man3/CMS_EncryptedData_decrypt.html]=man3/CMS_EncryptedData_decrypt.pod
DEPEND[man/man3/CMS_EncryptedData_decrypt.3]=man3/CMS_EncryptedData_decrypt.pod
GENERATE[man/man3/CMS_EncryptedData_decrypt.3]=man3/CMS_EncryptedData_decrypt.pod
DEPEND[html/man3/CMS_EncryptedData_encrypt.html]=man3/CMS_EncryptedData_encrypt.pod
GENERATE[html/man3/CMS_EncryptedData_encrypt.html]=man3/CMS_EncryptedData_encrypt.pod
DEPEND[man/man3/CMS_EncryptedData_encrypt.3]=man3/CMS_EncryptedData_encrypt.pod
GENERATE[man/man3/CMS_EncryptedData_encrypt.3]=man3/CMS_EncryptedData_encrypt.pod
DEPEND[html/man3/CMS_EnvelopedData_create.html]=man3/CMS_EnvelopedData_create.pod
GENERATE[html/man3/CMS_EnvelopedData_create.html]=man3/CMS_EnvelopedData_create.pod
DEPEND[man/man3/CMS_EnvelopedData_create.3]=man3/CMS_EnvelopedData_create.pod
GENERATE[man/man3/CMS_EnvelopedData_create.3]=man3/CMS_EnvelopedData_create.pod
DEPEND[html/man3/CMS_add0_cert.html]=man3/CMS_add0_cert.pod
GENERATE[html/man3/CMS_add0_cert.html]=man3/CMS_add0_cert.pod
DEPEND[man/man3/CMS_add0_cert.3]=man3/CMS_add0_cert.pod
GENERATE[man/man3/CMS_add0_cert.3]=man3/CMS_add0_cert.pod
DEPEND[html/man3/CMS_add1_recipient_cert.html]=man3/CMS_add1_recipient_cert.pod
GENERATE[html/man3/CMS_add1_recipient_cert.html]=man3/CMS_add1_recipient_cert.pod
DEPEND[man/man3/CMS_add1_recipient_cert.3]=man3/CMS_add1_recipient_cert.pod
GENERATE[man/man3/CMS_add1_recipient_cert.3]=man3/CMS_add1_recipient_cert.pod
DEPEND[html/man3/CMS_add1_signer.html]=man3/CMS_add1_signer.pod
GENERATE[html/man3/CMS_add1_signer.html]=man3/CMS_add1_signer.pod
DEPEND[man/man3/CMS_add1_signer.3]=man3/CMS_add1_signer.pod
GENERATE[man/man3/CMS_add1_signer.3]=man3/CMS_add1_signer.pod
DEPEND[html/man3/CMS_compress.html]=man3/CMS_compress.pod
GENERATE[html/man3/CMS_compress.html]=man3/CMS_compress.pod
DEPEND[man/man3/CMS_compress.3]=man3/CMS_compress.pod
GENERATE[man/man3/CMS_compress.3]=man3/CMS_compress.pod
DEPEND[html/man3/CMS_data_create.html]=man3/CMS_data_create.pod
GENERATE[html/man3/CMS_data_create.html]=man3/CMS_data_create.pod
DEPEND[man/man3/CMS_data_create.3]=man3/CMS_data_create.pod
GENERATE[man/man3/CMS_data_create.3]=man3/CMS_data_create.pod
DEPEND[html/man3/CMS_decrypt.html]=man3/CMS_decrypt.pod
GENERATE[html/man3/CMS_decrypt.html]=man3/CMS_decrypt.pod
DEPEND[man/man3/CMS_decrypt.3]=man3/CMS_decrypt.pod
GENERATE[man/man3/CMS_decrypt.3]=man3/CMS_decrypt.pod
DEPEND[html/man3/CMS_digest_create.html]=man3/CMS_digest_create.pod
GENERATE[html/man3/CMS_digest_create.html]=man3/CMS_digest_create.pod
DEPEND[man/man3/CMS_digest_create.3]=man3/CMS_digest_create.pod
GENERATE[man/man3/CMS_digest_create.3]=man3/CMS_digest_create.pod
DEPEND[html/man3/CMS_encrypt.html]=man3/CMS_encrypt.pod
GENERATE[html/man3/CMS_encrypt.html]=man3/CMS_encrypt.pod
DEPEND[man/man3/CMS_encrypt.3]=man3/CMS_encrypt.pod
GENERATE[man/man3/CMS_encrypt.3]=man3/CMS_encrypt.pod
DEPEND[html/man3/CMS_final.html]=man3/CMS_final.pod
GENERATE[html/man3/CMS_final.html]=man3/CMS_final.pod
DEPEND[man/man3/CMS_final.3]=man3/CMS_final.pod
GENERATE[man/man3/CMS_final.3]=man3/CMS_final.pod
DEPEND[html/man3/CMS_get0_RecipientInfos.html]=man3/CMS_get0_RecipientInfos.pod
GENERATE[html/man3/CMS_get0_RecipientInfos.html]=man3/CMS_get0_RecipientInfos.pod
DEPEND[man/man3/CMS_get0_RecipientInfos.3]=man3/CMS_get0_RecipientInfos.pod
GENERATE[man/man3/CMS_get0_RecipientInfos.3]=man3/CMS_get0_RecipientInfos.pod
DEPEND[html/man3/CMS_get0_SignerInfos.html]=man3/CMS_get0_SignerInfos.pod
GENERATE[html/man3/CMS_get0_SignerInfos.html]=man3/CMS_get0_SignerInfos.pod
DEPEND[man/man3/CMS_get0_SignerInfos.3]=man3/CMS_get0_SignerInfos.pod
GENERATE[man/man3/CMS_get0_SignerInfos.3]=man3/CMS_get0_SignerInfos.pod
DEPEND[html/man3/CMS_get0_type.html]=man3/CMS_get0_type.pod
GENERATE[html/man3/CMS_get0_type.html]=man3/CMS_get0_type.pod
DEPEND[man/man3/CMS_get0_type.3]=man3/CMS_get0_type.pod
GENERATE[man/man3/CMS_get0_type.3]=man3/CMS_get0_type.pod
DEPEND[html/man3/CMS_get1_ReceiptRequest.html]=man3/CMS_get1_ReceiptRequest.pod
GENERATE[html/man3/CMS_get1_ReceiptRequest.html]=man3/CMS_get1_ReceiptRequest.pod
DEPEND[man/man3/CMS_get1_ReceiptRequest.3]=man3/CMS_get1_ReceiptRequest.pod
GENERATE[man/man3/CMS_get1_ReceiptRequest.3]=man3/CMS_get1_ReceiptRequest.pod
DEPEND[html/man3/CMS_sign.html]=man3/CMS_sign.pod
GENERATE[html/man3/CMS_sign.html]=man3/CMS_sign.pod
DEPEND[man/man3/CMS_sign.3]=man3/CMS_sign.pod
GENERATE[man/man3/CMS_sign.3]=man3/CMS_sign.pod
DEPEND[html/man3/CMS_sign_receipt.html]=man3/CMS_sign_receipt.pod
GENERATE[html/man3/CMS_sign_receipt.html]=man3/CMS_sign_receipt.pod
DEPEND[man/man3/CMS_sign_receipt.3]=man3/CMS_sign_receipt.pod
GENERATE[man/man3/CMS_sign_receipt.3]=man3/CMS_sign_receipt.pod
DEPEND[html/man3/CMS_uncompress.html]=man3/CMS_uncompress.pod
GENERATE[html/man3/CMS_uncompress.html]=man3/CMS_uncompress.pod
DEPEND[man/man3/CMS_uncompress.3]=man3/CMS_uncompress.pod
GENERATE[man/man3/CMS_uncompress.3]=man3/CMS_uncompress.pod
DEPEND[html/man3/CMS_verify.html]=man3/CMS_verify.pod
GENERATE[html/man3/CMS_verify.html]=man3/CMS_verify.pod
DEPEND[man/man3/CMS_verify.3]=man3/CMS_verify.pod
GENERATE[man/man3/CMS_verify.3]=man3/CMS_verify.pod
DEPEND[html/man3/CMS_verify_receipt.html]=man3/CMS_verify_receipt.pod
GENERATE[html/man3/CMS_verify_receipt.html]=man3/CMS_verify_receipt.pod
DEPEND[man/man3/CMS_verify_receipt.3]=man3/CMS_verify_receipt.pod
GENERATE[man/man3/CMS_verify_receipt.3]=man3/CMS_verify_receipt.pod
DEPEND[html/man3/CONF_modules_free.html]=man3/CONF_modules_free.pod
GENERATE[html/man3/CONF_modules_free.html]=man3/CONF_modules_free.pod
DEPEND[man/man3/CONF_modules_free.3]=man3/CONF_modules_free.pod
GENERATE[man/man3/CONF_modules_free.3]=man3/CONF_modules_free.pod
DEPEND[html/man3/CONF_modules_load_file.html]=man3/CONF_modules_load_file.pod
GENERATE[html/man3/CONF_modules_load_file.html]=man3/CONF_modules_load_file.pod
DEPEND[man/man3/CONF_modules_load_file.3]=man3/CONF_modules_load_file.pod
GENERATE[man/man3/CONF_modules_load_file.3]=man3/CONF_modules_load_file.pod
DEPEND[html/man3/CRYPTO_THREAD_run_once.html]=man3/CRYPTO_THREAD_run_once.pod
GENERATE[html/man3/CRYPTO_THREAD_run_once.html]=man3/CRYPTO_THREAD_run_once.pod
DEPEND[man/man3/CRYPTO_THREAD_run_once.3]=man3/CRYPTO_THREAD_run_once.pod
GENERATE[man/man3/CRYPTO_THREAD_run_once.3]=man3/CRYPTO_THREAD_run_once.pod
DEPEND[html/man3/CRYPTO_get_ex_new_index.html]=man3/CRYPTO_get_ex_new_index.pod
GENERATE[html/man3/CRYPTO_get_ex_new_index.html]=man3/CRYPTO_get_ex_new_index.pod
DEPEND[man/man3/CRYPTO_get_ex_new_index.3]=man3/CRYPTO_get_ex_new_index.pod
GENERATE[man/man3/CRYPTO_get_ex_new_index.3]=man3/CRYPTO_get_ex_new_index.pod
DEPEND[html/man3/CRYPTO_memcmp.html]=man3/CRYPTO_memcmp.pod
GENERATE[html/man3/CRYPTO_memcmp.html]=man3/CRYPTO_memcmp.pod
DEPEND[man/man3/CRYPTO_memcmp.3]=man3/CRYPTO_memcmp.pod
GENERATE[man/man3/CRYPTO_memcmp.3]=man3/CRYPTO_memcmp.pod
DEPEND[html/man3/CTLOG_STORE_get0_log_by_id.html]=man3/CTLOG_STORE_get0_log_by_id.pod
GENERATE[html/man3/CTLOG_STORE_get0_log_by_id.html]=man3/CTLOG_STORE_get0_log_by_id.pod
DEPEND[man/man3/CTLOG_STORE_get0_log_by_id.3]=man3/CTLOG_STORE_get0_log_by_id.pod
GENERATE[man/man3/CTLOG_STORE_get0_log_by_id.3]=man3/CTLOG_STORE_get0_log_by_id.pod
DEPEND[html/man3/CTLOG_STORE_new.html]=man3/CTLOG_STORE_new.pod
GENERATE[html/man3/CTLOG_STORE_new.html]=man3/CTLOG_STORE_new.pod
DEPEND[man/man3/CTLOG_STORE_new.3]=man3/CTLOG_STORE_new.pod
GENERATE[man/man3/CTLOG_STORE_new.3]=man3/CTLOG_STORE_new.pod
DEPEND[html/man3/CTLOG_new.html]=man3/CTLOG_new.pod
GENERATE[html/man3/CTLOG_new.html]=man3/CTLOG_new.pod
DEPEND[man/man3/CTLOG_new.3]=man3/CTLOG_new.pod
GENERATE[man/man3/CTLOG_new.3]=man3/CTLOG_new.pod
DEPEND[html/man3/CT_POLICY_EVAL_CTX_new.html]=man3/CT_POLICY_EVAL_CTX_new.pod
GENERATE[html/man3/CT_POLICY_EVAL_CTX_new.html]=man3/CT_POLICY_EVAL_CTX_new.pod
DEPEND[man/man3/CT_POLICY_EVAL_CTX_new.3]=man3/CT_POLICY_EVAL_CTX_new.pod
GENERATE[man/man3/CT_POLICY_EVAL_CTX_new.3]=man3/CT_POLICY_EVAL_CTX_new.pod
DEPEND[html/man3/DEFINE_STACK_OF.html]=man3/DEFINE_STACK_OF.pod
GENERATE[html/man3/DEFINE_STACK_OF.html]=man3/DEFINE_STACK_OF.pod
DEPEND[man/man3/DEFINE_STACK_OF.3]=man3/DEFINE_STACK_OF.pod
GENERATE[man/man3/DEFINE_STACK_OF.3]=man3/DEFINE_STACK_OF.pod
DEPEND[html/man3/DES_random_key.html]=man3/DES_random_key.pod
GENERATE[html/man3/DES_random_key.html]=man3/DES_random_key.pod
DEPEND[man/man3/DES_random_key.3]=man3/DES_random_key.pod
GENERATE[man/man3/DES_random_key.3]=man3/DES_random_key.pod
DEPEND[html/man3/DH_generate_key.html]=man3/DH_generate_key.pod
GENERATE[html/man3/DH_generate_key.html]=man3/DH_generate_key.pod
DEPEND[man/man3/DH_generate_key.3]=man3/DH_generate_key.pod
GENERATE[man/man3/DH_generate_key.3]=man3/DH_generate_key.pod
DEPEND[html/man3/DH_generate_parameters.html]=man3/DH_generate_parameters.pod
GENERATE[html/man3/DH_generate_parameters.html]=man3/DH_generate_parameters.pod
DEPEND[man/man3/DH_generate_parameters.3]=man3/DH_generate_parameters.pod
GENERATE[man/man3/DH_generate_parameters.3]=man3/DH_generate_parameters.pod
DEPEND[html/man3/DH_get0_pqg.html]=man3/DH_get0_pqg.pod
GENERATE[html/man3/DH_get0_pqg.html]=man3/DH_get0_pqg.pod
DEPEND[man/man3/DH_get0_pqg.3]=man3/DH_get0_pqg.pod
GENERATE[man/man3/DH_get0_pqg.3]=man3/DH_get0_pqg.pod
DEPEND[html/man3/DH_get_1024_160.html]=man3/DH_get_1024_160.pod
GENERATE[html/man3/DH_get_1024_160.html]=man3/DH_get_1024_160.pod
DEPEND[man/man3/DH_get_1024_160.3]=man3/DH_get_1024_160.pod
GENERATE[man/man3/DH_get_1024_160.3]=man3/DH_get_1024_160.pod
DEPEND[html/man3/DH_meth_new.html]=man3/DH_meth_new.pod
GENERATE[html/man3/DH_meth_new.html]=man3/DH_meth_new.pod
DEPEND[man/man3/DH_meth_new.3]=man3/DH_meth_new.pod
GENERATE[man/man3/DH_meth_new.3]=man3/DH_meth_new.pod
DEPEND[html/man3/DH_new.html]=man3/DH_new.pod
GENERATE[html/man3/DH_new.html]=man3/DH_new.pod
DEPEND[man/man3/DH_new.3]=man3/DH_new.pod
GENERATE[man/man3/DH_new.3]=man3/DH_new.pod
DEPEND[html/man3/DH_new_by_nid.html]=man3/DH_new_by_nid.pod
GENERATE[html/man3/DH_new_by_nid.html]=man3/DH_new_by_nid.pod
DEPEND[man/man3/DH_new_by_nid.3]=man3/DH_new_by_nid.pod
GENERATE[man/man3/DH_new_by_nid.3]=man3/DH_new_by_nid.pod
DEPEND[html/man3/DH_set_method.html]=man3/DH_set_method.pod
GENERATE[html/man3/DH_set_method.html]=man3/DH_set_method.pod
DEPEND[man/man3/DH_set_method.3]=man3/DH_set_method.pod
GENERATE[man/man3/DH_set_method.3]=man3/DH_set_method.pod
DEPEND[html/man3/DH_size.html]=man3/DH_size.pod
GENERATE[html/man3/DH_size.html]=man3/DH_size.pod
DEPEND[man/man3/DH_size.3]=man3/DH_size.pod
GENERATE[man/man3/DH_size.3]=man3/DH_size.pod
DEPEND[html/man3/DSA_SIG_new.html]=man3/DSA_SIG_new.pod
GENERATE[html/man3/DSA_SIG_new.html]=man3/DSA_SIG_new.pod
DEPEND[man/man3/DSA_SIG_new.3]=man3/DSA_SIG_new.pod
GENERATE[man/man3/DSA_SIG_new.3]=man3/DSA_SIG_new.pod
DEPEND[html/man3/DSA_do_sign.html]=man3/DSA_do_sign.pod
GENERATE[html/man3/DSA_do_sign.html]=man3/DSA_do_sign.pod
DEPEND[man/man3/DSA_do_sign.3]=man3/DSA_do_sign.pod
GENERATE[man/man3/DSA_do_sign.3]=man3/DSA_do_sign.pod
DEPEND[html/man3/DSA_dup_DH.html]=man3/DSA_dup_DH.pod
GENERATE[html/man3/DSA_dup_DH.html]=man3/DSA_dup_DH.pod
DEPEND[man/man3/DSA_dup_DH.3]=man3/DSA_dup_DH.pod
GENERATE[man/man3/DSA_dup_DH.3]=man3/DSA_dup_DH.pod
DEPEND[html/man3/DSA_generate_key.html]=man3/DSA_generate_key.pod
GENERATE[html/man3/DSA_generate_key.html]=man3/DSA_generate_key.pod
DEPEND[man/man3/DSA_generate_key.3]=man3/DSA_generate_key.pod
GENERATE[man/man3/DSA_generate_key.3]=man3/DSA_generate_key.pod
DEPEND[html/man3/DSA_generate_parameters.html]=man3/DSA_generate_parameters.pod
GENERATE[html/man3/DSA_generate_parameters.html]=man3/DSA_generate_parameters.pod
DEPEND[man/man3/DSA_generate_parameters.3]=man3/DSA_generate_parameters.pod
GENERATE[man/man3/DSA_generate_parameters.3]=man3/DSA_generate_parameters.pod
DEPEND[html/man3/DSA_get0_pqg.html]=man3/DSA_get0_pqg.pod
GENERATE[html/man3/DSA_get0_pqg.html]=man3/DSA_get0_pqg.pod
DEPEND[man/man3/DSA_get0_pqg.3]=man3/DSA_get0_pqg.pod
GENERATE[man/man3/DSA_get0_pqg.3]=man3/DSA_get0_pqg.pod
DEPEND[html/man3/DSA_meth_new.html]=man3/DSA_meth_new.pod
GENERATE[html/man3/DSA_meth_new.html]=man3/DSA_meth_new.pod
DEPEND[man/man3/DSA_meth_new.3]=man3/DSA_meth_new.pod
GENERATE[man/man3/DSA_meth_new.3]=man3/DSA_meth_new.pod
DEPEND[html/man3/DSA_new.html]=man3/DSA_new.pod
GENERATE[html/man3/DSA_new.html]=man3/DSA_new.pod
DEPEND[man/man3/DSA_new.3]=man3/DSA_new.pod
GENERATE[man/man3/DSA_new.3]=man3/DSA_new.pod
DEPEND[html/man3/DSA_set_method.html]=man3/DSA_set_method.pod
GENERATE[html/man3/DSA_set_method.html]=man3/DSA_set_method.pod
DEPEND[man/man3/DSA_set_method.3]=man3/DSA_set_method.pod
GENERATE[man/man3/DSA_set_method.3]=man3/DSA_set_method.pod
DEPEND[html/man3/DSA_sign.html]=man3/DSA_sign.pod
GENERATE[html/man3/DSA_sign.html]=man3/DSA_sign.pod
DEPEND[man/man3/DSA_sign.3]=man3/DSA_sign.pod
GENERATE[man/man3/DSA_sign.3]=man3/DSA_sign.pod
DEPEND[html/man3/DSA_size.html]=man3/DSA_size.pod
GENERATE[html/man3/DSA_size.html]=man3/DSA_size.pod
DEPEND[man/man3/DSA_size.3]=man3/DSA_size.pod
GENERATE[man/man3/DSA_size.3]=man3/DSA_size.pod
DEPEND[html/man3/DTLS_get_data_mtu.html]=man3/DTLS_get_data_mtu.pod
GENERATE[html/man3/DTLS_get_data_mtu.html]=man3/DTLS_get_data_mtu.pod
DEPEND[man/man3/DTLS_get_data_mtu.3]=man3/DTLS_get_data_mtu.pod
GENERATE[man/man3/DTLS_get_data_mtu.3]=man3/DTLS_get_data_mtu.pod
DEPEND[html/man3/DTLS_set_timer_cb.html]=man3/DTLS_set_timer_cb.pod
GENERATE[html/man3/DTLS_set_timer_cb.html]=man3/DTLS_set_timer_cb.pod
DEPEND[man/man3/DTLS_set_timer_cb.3]=man3/DTLS_set_timer_cb.pod
GENERATE[man/man3/DTLS_set_timer_cb.3]=man3/DTLS_set_timer_cb.pod
DEPEND[html/man3/DTLSv1_listen.html]=man3/DTLSv1_listen.pod
GENERATE[html/man3/DTLSv1_listen.html]=man3/DTLSv1_listen.pod
DEPEND[man/man3/DTLSv1_listen.3]=man3/DTLSv1_listen.pod
GENERATE[man/man3/DTLSv1_listen.3]=man3/DTLSv1_listen.pod
DEPEND[html/man3/ECDSA_SIG_new.html]=man3/ECDSA_SIG_new.pod
GENERATE[html/man3/ECDSA_SIG_new.html]=man3/ECDSA_SIG_new.pod
DEPEND[man/man3/ECDSA_SIG_new.3]=man3/ECDSA_SIG_new.pod
GENERATE[man/man3/ECDSA_SIG_new.3]=man3/ECDSA_SIG_new.pod
DEPEND[html/man3/ECDSA_sign.html]=man3/ECDSA_sign.pod
GENERATE[html/man3/ECDSA_sign.html]=man3/ECDSA_sign.pod
DEPEND[man/man3/ECDSA_sign.3]=man3/ECDSA_sign.pod
GENERATE[man/man3/ECDSA_sign.3]=man3/ECDSA_sign.pod
DEPEND[html/man3/ECPKParameters_print.html]=man3/ECPKParameters_print.pod
GENERATE[html/man3/ECPKParameters_print.html]=man3/ECPKParameters_print.pod
DEPEND[man/man3/ECPKParameters_print.3]=man3/ECPKParameters_print.pod
GENERATE[man/man3/ECPKParameters_print.3]=man3/ECPKParameters_print.pod
DEPEND[html/man3/EC_GFp_simple_method.html]=man3/EC_GFp_simple_method.pod
GENERATE[html/man3/EC_GFp_simple_method.html]=man3/EC_GFp_simple_method.pod
DEPEND[man/man3/EC_GFp_simple_method.3]=man3/EC_GFp_simple_method.pod
GENERATE[man/man3/EC_GFp_simple_method.3]=man3/EC_GFp_simple_method.pod
DEPEND[html/man3/EC_GROUP_copy.html]=man3/EC_GROUP_copy.pod
GENERATE[html/man3/EC_GROUP_copy.html]=man3/EC_GROUP_copy.pod
DEPEND[man/man3/EC_GROUP_copy.3]=man3/EC_GROUP_copy.pod
GENERATE[man/man3/EC_GROUP_copy.3]=man3/EC_GROUP_copy.pod
DEPEND[html/man3/EC_GROUP_new.html]=man3/EC_GROUP_new.pod
GENERATE[html/man3/EC_GROUP_new.html]=man3/EC_GROUP_new.pod
DEPEND[man/man3/EC_GROUP_new.3]=man3/EC_GROUP_new.pod
GENERATE[man/man3/EC_GROUP_new.3]=man3/EC_GROUP_new.pod
DEPEND[html/man3/EC_KEY_get_enc_flags.html]=man3/EC_KEY_get_enc_flags.pod
GENERATE[html/man3/EC_KEY_get_enc_flags.html]=man3/EC_KEY_get_enc_flags.pod
DEPEND[man/man3/EC_KEY_get_enc_flags.3]=man3/EC_KEY_get_enc_flags.pod
GENERATE[man/man3/EC_KEY_get_enc_flags.3]=man3/EC_KEY_get_enc_flags.pod
DEPEND[html/man3/EC_KEY_new.html]=man3/EC_KEY_new.pod
GENERATE[html/man3/EC_KEY_new.html]=man3/EC_KEY_new.pod
DEPEND[man/man3/EC_KEY_new.3]=man3/EC_KEY_new.pod
GENERATE[man/man3/EC_KEY_new.3]=man3/EC_KEY_new.pod
DEPEND[html/man3/EC_POINT_add.html]=man3/EC_POINT_add.pod
GENERATE[html/man3/EC_POINT_add.html]=man3/EC_POINT_add.pod
DEPEND[man/man3/EC_POINT_add.3]=man3/EC_POINT_add.pod
GENERATE[man/man3/EC_POINT_add.3]=man3/EC_POINT_add.pod
DEPEND[html/man3/EC_POINT_new.html]=man3/EC_POINT_new.pod
GENERATE[html/man3/EC_POINT_new.html]=man3/EC_POINT_new.pod
DEPEND[man/man3/EC_POINT_new.3]=man3/EC_POINT_new.pod
GENERATE[man/man3/EC_POINT_new.3]=man3/EC_POINT_new.pod
DEPEND[html/man3/ENGINE_add.html]=man3/ENGINE_add.pod
GENERATE[html/man3/ENGINE_add.html]=man3/ENGINE_add.pod
DEPEND[man/man3/ENGINE_add.3]=man3/ENGINE_add.pod
GENERATE[man/man3/ENGINE_add.3]=man3/ENGINE_add.pod
DEPEND[html/man3/ERR_GET_LIB.html]=man3/ERR_GET_LIB.pod
GENERATE[html/man3/ERR_GET_LIB.html]=man3/ERR_GET_LIB.pod
DEPEND[man/man3/ERR_GET_LIB.3]=man3/ERR_GET_LIB.pod
GENERATE[man/man3/ERR_GET_LIB.3]=man3/ERR_GET_LIB.pod
DEPEND[html/man3/ERR_clear_error.html]=man3/ERR_clear_error.pod
GENERATE[html/man3/ERR_clear_error.html]=man3/ERR_clear_error.pod
DEPEND[man/man3/ERR_clear_error.3]=man3/ERR_clear_error.pod
GENERATE[man/man3/ERR_clear_error.3]=man3/ERR_clear_error.pod
DEPEND[html/man3/ERR_error_string.html]=man3/ERR_error_string.pod
GENERATE[html/man3/ERR_error_string.html]=man3/ERR_error_string.pod
DEPEND[man/man3/ERR_error_string.3]=man3/ERR_error_string.pod
GENERATE[man/man3/ERR_error_string.3]=man3/ERR_error_string.pod
DEPEND[html/man3/ERR_get_error.html]=man3/ERR_get_error.pod
GENERATE[html/man3/ERR_get_error.html]=man3/ERR_get_error.pod
DEPEND[man/man3/ERR_get_error.3]=man3/ERR_get_error.pod
GENERATE[man/man3/ERR_get_error.3]=man3/ERR_get_error.pod
DEPEND[html/man3/ERR_load_crypto_strings.html]=man3/ERR_load_crypto_strings.pod
GENERATE[html/man3/ERR_load_crypto_strings.html]=man3/ERR_load_crypto_strings.pod
DEPEND[man/man3/ERR_load_crypto_strings.3]=man3/ERR_load_crypto_strings.pod
GENERATE[man/man3/ERR_load_crypto_strings.3]=man3/ERR_load_crypto_strings.pod
DEPEND[html/man3/ERR_load_strings.html]=man3/ERR_load_strings.pod
GENERATE[html/man3/ERR_load_strings.html]=man3/ERR_load_strings.pod
DEPEND[man/man3/ERR_load_strings.3]=man3/ERR_load_strings.pod
GENERATE[man/man3/ERR_load_strings.3]=man3/ERR_load_strings.pod
DEPEND[html/man3/ERR_new.html]=man3/ERR_new.pod
GENERATE[html/man3/ERR_new.html]=man3/ERR_new.pod
DEPEND[man/man3/ERR_new.3]=man3/ERR_new.pod
GENERATE[man/man3/ERR_new.3]=man3/ERR_new.pod
DEPEND[html/man3/ERR_print_errors.html]=man3/ERR_print_errors.pod
GENERATE[html/man3/ERR_print_errors.html]=man3/ERR_print_errors.pod
DEPEND[man/man3/ERR_print_errors.3]=man3/ERR_print_errors.pod
GENERATE[man/man3/ERR_print_errors.3]=man3/ERR_print_errors.pod
DEPEND[html/man3/ERR_put_error.html]=man3/ERR_put_error.pod
GENERATE[html/man3/ERR_put_error.html]=man3/ERR_put_error.pod
DEPEND[man/man3/ERR_put_error.3]=man3/ERR_put_error.pod
GENERATE[man/man3/ERR_put_error.3]=man3/ERR_put_error.pod
DEPEND[html/man3/ERR_remove_state.html]=man3/ERR_remove_state.pod
GENERATE[html/man3/ERR_remove_state.html]=man3/ERR_remove_state.pod
DEPEND[man/man3/ERR_remove_state.3]=man3/ERR_remove_state.pod
GENERATE[man/man3/ERR_remove_state.3]=man3/ERR_remove_state.pod
DEPEND[html/man3/ERR_set_mark.html]=man3/ERR_set_mark.pod
GENERATE[html/man3/ERR_set_mark.html]=man3/ERR_set_mark.pod
DEPEND[man/man3/ERR_set_mark.3]=man3/ERR_set_mark.pod
GENERATE[man/man3/ERR_set_mark.3]=man3/ERR_set_mark.pod
DEPEND[html/man3/EVP_ASYM_CIPHER_free.html]=man3/EVP_ASYM_CIPHER_free.pod
GENERATE[html/man3/EVP_ASYM_CIPHER_free.html]=man3/EVP_ASYM_CIPHER_free.pod
DEPEND[man/man3/EVP_ASYM_CIPHER_free.3]=man3/EVP_ASYM_CIPHER_free.pod
GENERATE[man/man3/EVP_ASYM_CIPHER_free.3]=man3/EVP_ASYM_CIPHER_free.pod
DEPEND[html/man3/EVP_BytesToKey.html]=man3/EVP_BytesToKey.pod
GENERATE[html/man3/EVP_BytesToKey.html]=man3/EVP_BytesToKey.pod
DEPEND[man/man3/EVP_BytesToKey.3]=man3/EVP_BytesToKey.pod
GENERATE[man/man3/EVP_BytesToKey.3]=man3/EVP_BytesToKey.pod
DEPEND[html/man3/EVP_CIPHER_CTX_get_cipher_data.html]=man3/EVP_CIPHER_CTX_get_cipher_data.pod
GENERATE[html/man3/EVP_CIPHER_CTX_get_cipher_data.html]=man3/EVP_CIPHER_CTX_get_cipher_data.pod
DEPEND[man/man3/EVP_CIPHER_CTX_get_cipher_data.3]=man3/EVP_CIPHER_CTX_get_cipher_data.pod
GENERATE[man/man3/EVP_CIPHER_CTX_get_cipher_data.3]=man3/EVP_CIPHER_CTX_get_cipher_data.pod
DEPEND[html/man3/EVP_CIPHER_CTX_get_original_iv.html]=man3/EVP_CIPHER_CTX_get_original_iv.pod
GENERATE[html/man3/EVP_CIPHER_CTX_get_original_iv.html]=man3/EVP_CIPHER_CTX_get_original_iv.pod
DEPEND[man/man3/EVP_CIPHER_CTX_get_original_iv.3]=man3/EVP_CIPHER_CTX_get_original_iv.pod
GENERATE[man/man3/EVP_CIPHER_CTX_get_original_iv.3]=man3/EVP_CIPHER_CTX_get_original_iv.pod
DEPEND[html/man3/EVP_CIPHER_meth_new.html]=man3/EVP_CIPHER_meth_new.pod
GENERATE[html/man3/EVP_CIPHER_meth_new.html]=man3/EVP_CIPHER_meth_new.pod
DEPEND[man/man3/EVP_CIPHER_meth_new.3]=man3/EVP_CIPHER_meth_new.pod
GENERATE[man/man3/EVP_CIPHER_meth_new.3]=man3/EVP_CIPHER_meth_new.pod
DEPEND[html/man3/EVP_DigestInit.html]=man3/EVP_DigestInit.pod
GENERATE[html/man3/EVP_DigestInit.html]=man3/EVP_DigestInit.pod
DEPEND[man/man3/EVP_DigestInit.3]=man3/EVP_DigestInit.pod
GENERATE[man/man3/EVP_DigestInit.3]=man3/EVP_DigestInit.pod
DEPEND[html/man3/EVP_DigestSignInit.html]=man3/EVP_DigestSignInit.pod
GENERATE[html/man3/EVP_DigestSignInit.html]=man3/EVP_DigestSignInit.pod
DEPEND[man/man3/EVP_DigestSignInit.3]=man3/EVP_DigestSignInit.pod
GENERATE[man/man3/EVP_DigestSignInit.3]=man3/EVP_DigestSignInit.pod
DEPEND[html/man3/EVP_DigestVerifyInit.html]=man3/EVP_DigestVerifyInit.pod
GENERATE[html/man3/EVP_DigestVerifyInit.html]=man3/EVP_DigestVerifyInit.pod
DEPEND[man/man3/EVP_DigestVerifyInit.3]=man3/EVP_DigestVerifyInit.pod
GENERATE[man/man3/EVP_DigestVerifyInit.3]=man3/EVP_DigestVerifyInit.pod
DEPEND[html/man3/EVP_EncodeInit.html]=man3/EVP_EncodeInit.pod
GENERATE[html/man3/EVP_EncodeInit.html]=man3/EVP_EncodeInit.pod
DEPEND[man/man3/EVP_EncodeInit.3]=man3/EVP_EncodeInit.pod
GENERATE[man/man3/EVP_EncodeInit.3]=man3/EVP_EncodeInit.pod
DEPEND[html/man3/EVP_EncryptInit.html]=man3/EVP_EncryptInit.pod
GENERATE[html/man3/EVP_EncryptInit.html]=man3/EVP_EncryptInit.pod
DEPEND[man/man3/EVP_EncryptInit.3]=man3/EVP_EncryptInit.pod
GENERATE[man/man3/EVP_EncryptInit.3]=man3/EVP_EncryptInit.pod
DEPEND[html/man3/EVP_KDF.html]=man3/EVP_KDF.pod
GENERATE[html/man3/EVP_KDF.html]=man3/EVP_KDF.pod
DEPEND[man/man3/EVP_KDF.3]=man3/EVP_KDF.pod
GENERATE[man/man3/EVP_KDF.3]=man3/EVP_KDF.pod
DEPEND[html/man3/EVP_KEM_free.html]=man3/EVP_KEM_free.pod
GENERATE[html/man3/EVP_KEM_free.html]=man3/EVP_KEM_free.pod
DEPEND[man/man3/EVP_KEM_free.3]=man3/EVP_KEM_free.pod
GENERATE[man/man3/EVP_KEM_free.3]=man3/EVP_KEM_free.pod
DEPEND[html/man3/EVP_KEYEXCH_free.html]=man3/EVP_KEYEXCH_free.pod
GENERATE[html/man3/EVP_KEYEXCH_free.html]=man3/EVP_KEYEXCH_free.pod
DEPEND[man/man3/EVP_KEYEXCH_free.3]=man3/EVP_KEYEXCH_free.pod
GENERATE[man/man3/EVP_KEYEXCH_free.3]=man3/EVP_KEYEXCH_free.pod
DEPEND[html/man3/EVP_KEYMGMT.html]=man3/EVP_KEYMGMT.pod
GENERATE[html/man3/EVP_KEYMGMT.html]=man3/EVP_KEYMGMT.pod
DEPEND[man/man3/EVP_KEYMGMT.3]=man3/EVP_KEYMGMT.pod
GENERATE[man/man3/EVP_KEYMGMT.3]=man3/EVP_KEYMGMT.pod
DEPEND[html/man3/EVP_MAC.html]=man3/EVP_MAC.pod
GENERATE[html/man3/EVP_MAC.html]=man3/EVP_MAC.pod
DEPEND[man/man3/EVP_MAC.3]=man3/EVP_MAC.pod
GENERATE[man/man3/EVP_MAC.3]=man3/EVP_MAC.pod
DEPEND[html/man3/EVP_MD_meth_new.html]=man3/EVP_MD_meth_new.pod
GENERATE[html/man3/EVP_MD_meth_new.html]=man3/EVP_MD_meth_new.pod
DEPEND[man/man3/EVP_MD_meth_new.3]=man3/EVP_MD_meth_new.pod
GENERATE[man/man3/EVP_MD_meth_new.3]=man3/EVP_MD_meth_new.pod
DEPEND[html/man3/EVP_OpenInit.html]=man3/EVP_OpenInit.pod
GENERATE[html/man3/EVP_OpenInit.html]=man3/EVP_OpenInit.pod
DEPEND[man/man3/EVP_OpenInit.3]=man3/EVP_OpenInit.pod
GENERATE[man/man3/EVP_OpenInit.3]=man3/EVP_OpenInit.pod
DEPEND[html/man3/EVP_PBE_CipherInit.html]=man3/EVP_PBE_CipherInit.pod
GENERATE[html/man3/EVP_PBE_CipherInit.html]=man3/EVP_PBE_CipherInit.pod
DEPEND[man/man3/EVP_PBE_CipherInit.3]=man3/EVP_PBE_CipherInit.pod
GENERATE[man/man3/EVP_PBE_CipherInit.3]=man3/EVP_PBE_CipherInit.pod
DEPEND[html/man3/EVP_PKEY2PKCS8.html]=man3/EVP_PKEY2PKCS8.pod
GENERATE[html/man3/EVP_PKEY2PKCS8.html]=man3/EVP_PKEY2PKCS8.pod
DEPEND[man/man3/EVP_PKEY2PKCS8.3]=man3/EVP_PKEY2PKCS8.pod
GENERATE[man/man3/EVP_PKEY2PKCS8.3]=man3/EVP_PKEY2PKCS8.pod
DEPEND[html/man3/EVP_PKEY_ASN1_METHOD.html]=man3/EVP_PKEY_ASN1_METHOD.pod
GENERATE[html/man3/EVP_PKEY_ASN1_METHOD.html]=man3/EVP_PKEY_ASN1_METHOD.pod
DEPEND[man/man3/EVP_PKEY_ASN1_METHOD.3]=man3/EVP_PKEY_ASN1_METHOD.pod
GENERATE[man/man3/EVP_PKEY_ASN1_METHOD.3]=man3/EVP_PKEY_ASN1_METHOD.pod
DEPEND[html/man3/EVP_PKEY_CTX_ctrl.html]=man3/EVP_PKEY_CTX_ctrl.pod
GENERATE[html/man3/EVP_PKEY_CTX_ctrl.html]=man3/EVP_PKEY_CTX_ctrl.pod
DEPEND[man/man3/EVP_PKEY_CTX_ctrl.3]=man3/EVP_PKEY_CTX_ctrl.pod
GENERATE[man/man3/EVP_PKEY_CTX_ctrl.3]=man3/EVP_PKEY_CTX_ctrl.pod
DEPEND[html/man3/EVP_PKEY_CTX_get0_libctx.html]=man3/EVP_PKEY_CTX_get0_libctx.pod
GENERATE[html/man3/EVP_PKEY_CTX_get0_libctx.html]=man3/EVP_PKEY_CTX_get0_libctx.pod
DEPEND[man/man3/EVP_PKEY_CTX_get0_libctx.3]=man3/EVP_PKEY_CTX_get0_libctx.pod
GENERATE[man/man3/EVP_PKEY_CTX_get0_libctx.3]=man3/EVP_PKEY_CTX_get0_libctx.pod
DEPEND[html/man3/EVP_PKEY_CTX_get0_pkey.html]=man3/EVP_PKEY_CTX_get0_pkey.pod
GENERATE[html/man3/EVP_PKEY_CTX_get0_pkey.html]=man3/EVP_PKEY_CTX_get0_pkey.pod
DEPEND[man/man3/EVP_PKEY_CTX_get0_pkey.3]=man3/EVP_PKEY_CTX_get0_pkey.pod
GENERATE[man/man3/EVP_PKEY_CTX_get0_pkey.3]=man3/EVP_PKEY_CTX_get0_pkey.pod
DEPEND[html/man3/EVP_PKEY_CTX_new.html]=man3/EVP_PKEY_CTX_new.pod
GENERATE[html/man3/EVP_PKEY_CTX_new.html]=man3/EVP_PKEY_CTX_new.pod
DEPEND[man/man3/EVP_PKEY_CTX_new.3]=man3/EVP_PKEY_CTX_new.pod
GENERATE[man/man3/EVP_PKEY_CTX_new.3]=man3/EVP_PKEY_CTX_new.pod
DEPEND[html/man3/EVP_PKEY_CTX_set1_pbe_pass.html]=man3/EVP_PKEY_CTX_set1_pbe_pass.pod
GENERATE[html/man3/EVP_PKEY_CTX_set1_pbe_pass.html]=man3/EVP_PKEY_CTX_set1_pbe_pass.pod
DEPEND[man/man3/EVP_PKEY_CTX_set1_pbe_pass.3]=man3/EVP_PKEY_CTX_set1_pbe_pass.pod
GENERATE[man/man3/EVP_PKEY_CTX_set1_pbe_pass.3]=man3/EVP_PKEY_CTX_set1_pbe_pass.pod
DEPEND[html/man3/EVP_PKEY_CTX_set_hkdf_md.html]=man3/EVP_PKEY_CTX_set_hkdf_md.pod
GENERATE[html/man3/EVP_PKEY_CTX_set_hkdf_md.html]=man3/EVP_PKEY_CTX_set_hkdf_md.pod
DEPEND[man/man3/EVP_PKEY_CTX_set_hkdf_md.3]=man3/EVP_PKEY_CTX_set_hkdf_md.pod
GENERATE[man/man3/EVP_PKEY_CTX_set_hkdf_md.3]=man3/EVP_PKEY_CTX_set_hkdf_md.pod
DEPEND[html/man3/EVP_PKEY_CTX_set_params.html]=man3/EVP_PKEY_CTX_set_params.pod
GENERATE[html/man3/EVP_PKEY_CTX_set_params.html]=man3/EVP_PKEY_CTX_set_params.pod
DEPEND[man/man3/EVP_PKEY_CTX_set_params.3]=man3/EVP_PKEY_CTX_set_params.pod
GENERATE[man/man3/EVP_PKEY_CTX_set_params.3]=man3/EVP_PKEY_CTX_set_params.pod
DEPEND[html/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.html]=man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
GENERATE[html/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.html]=man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
DEPEND[man/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.3]=man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
GENERATE[man/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.3]=man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
DEPEND[html/man3/EVP_PKEY_CTX_set_scrypt_N.html]=man3/EVP_PKEY_CTX_set_scrypt_N.pod
GENERATE[html/man3/EVP_PKEY_CTX_set_scrypt_N.html]=man3/EVP_PKEY_CTX_set_scrypt_N.pod
DEPEND[man/man3/EVP_PKEY_CTX_set_scrypt_N.3]=man3/EVP_PKEY_CTX_set_scrypt_N.pod
GENERATE[man/man3/EVP_PKEY_CTX_set_scrypt_N.3]=man3/EVP_PKEY_CTX_set_scrypt_N.pod
DEPEND[html/man3/EVP_PKEY_CTX_set_tls1_prf_md.html]=man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
GENERATE[html/man3/EVP_PKEY_CTX_set_tls1_prf_md.html]=man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
DEPEND[man/man3/EVP_PKEY_CTX_set_tls1_prf_md.3]=man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
GENERATE[man/man3/EVP_PKEY_CTX_set_tls1_prf_md.3]=man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
DEPEND[html/man3/EVP_PKEY_asn1_get_count.html]=man3/EVP_PKEY_asn1_get_count.pod
GENERATE[html/man3/EVP_PKEY_asn1_get_count.html]=man3/EVP_PKEY_asn1_get_count.pod
DEPEND[man/man3/EVP_PKEY_asn1_get_count.3]=man3/EVP_PKEY_asn1_get_count.pod
GENERATE[man/man3/EVP_PKEY_asn1_get_count.3]=man3/EVP_PKEY_asn1_get_count.pod
DEPEND[html/man3/EVP_PKEY_check.html]=man3/EVP_PKEY_check.pod
GENERATE[html/man3/EVP_PKEY_check.html]=man3/EVP_PKEY_check.pod
DEPEND[man/man3/EVP_PKEY_check.3]=man3/EVP_PKEY_check.pod
GENERATE[man/man3/EVP_PKEY_check.3]=man3/EVP_PKEY_check.pod
DEPEND[html/man3/EVP_PKEY_copy_parameters.html]=man3/EVP_PKEY_copy_parameters.pod
GENERATE[html/man3/EVP_PKEY_copy_parameters.html]=man3/EVP_PKEY_copy_parameters.pod
DEPEND[man/man3/EVP_PKEY_copy_parameters.3]=man3/EVP_PKEY_copy_parameters.pod
GENERATE[man/man3/EVP_PKEY_copy_parameters.3]=man3/EVP_PKEY_copy_parameters.pod
DEPEND[html/man3/EVP_PKEY_decapsulate.html]=man3/EVP_PKEY_decapsulate.pod
GENERATE[html/man3/EVP_PKEY_decapsulate.html]=man3/EVP_PKEY_decapsulate.pod
DEPEND[man/man3/EVP_PKEY_decapsulate.3]=man3/EVP_PKEY_decapsulate.pod
GENERATE[man/man3/EVP_PKEY_decapsulate.3]=man3/EVP_PKEY_decapsulate.pod
DEPEND[html/man3/EVP_PKEY_decrypt.html]=man3/EVP_PKEY_decrypt.pod
GENERATE[html/man3/EVP_PKEY_decrypt.html]=man3/EVP_PKEY_decrypt.pod
DEPEND[man/man3/EVP_PKEY_decrypt.3]=man3/EVP_PKEY_decrypt.pod
GENERATE[man/man3/EVP_PKEY_decrypt.3]=man3/EVP_PKEY_decrypt.pod
DEPEND[html/man3/EVP_PKEY_derive.html]=man3/EVP_PKEY_derive.pod
GENERATE[html/man3/EVP_PKEY_derive.html]=man3/EVP_PKEY_derive.pod
DEPEND[man/man3/EVP_PKEY_derive.3]=man3/EVP_PKEY_derive.pod
GENERATE[man/man3/EVP_PKEY_derive.3]=man3/EVP_PKEY_derive.pod
DEPEND[html/man3/EVP_PKEY_digestsign_supports_digest.html]=man3/EVP_PKEY_digestsign_supports_digest.pod
GENERATE[html/man3/EVP_PKEY_digestsign_supports_digest.html]=man3/EVP_PKEY_digestsign_supports_digest.pod
DEPEND[man/man3/EVP_PKEY_digestsign_supports_digest.3]=man3/EVP_PKEY_digestsign_supports_digest.pod
GENERATE[man/man3/EVP_PKEY_digestsign_supports_digest.3]=man3/EVP_PKEY_digestsign_supports_digest.pod
DEPEND[html/man3/EVP_PKEY_encapsulate.html]=man3/EVP_PKEY_encapsulate.pod
GENERATE[html/man3/EVP_PKEY_encapsulate.html]=man3/EVP_PKEY_encapsulate.pod
DEPEND[man/man3/EVP_PKEY_encapsulate.3]=man3/EVP_PKEY_encapsulate.pod
GENERATE[man/man3/EVP_PKEY_encapsulate.3]=man3/EVP_PKEY_encapsulate.pod
DEPEND[html/man3/EVP_PKEY_encrypt.html]=man3/EVP_PKEY_encrypt.pod
GENERATE[html/man3/EVP_PKEY_encrypt.html]=man3/EVP_PKEY_encrypt.pod
DEPEND[man/man3/EVP_PKEY_encrypt.3]=man3/EVP_PKEY_encrypt.pod
GENERATE[man/man3/EVP_PKEY_encrypt.3]=man3/EVP_PKEY_encrypt.pod
DEPEND[html/man3/EVP_PKEY_fromdata.html]=man3/EVP_PKEY_fromdata.pod
GENERATE[html/man3/EVP_PKEY_fromdata.html]=man3/EVP_PKEY_fromdata.pod
DEPEND[man/man3/EVP_PKEY_fromdata.3]=man3/EVP_PKEY_fromdata.pod
GENERATE[man/man3/EVP_PKEY_fromdata.3]=man3/EVP_PKEY_fromdata.pod
DEPEND[html/man3/EVP_PKEY_get_default_digest_nid.html]=man3/EVP_PKEY_get_default_digest_nid.pod
GENERATE[html/man3/EVP_PKEY_get_default_digest_nid.html]=man3/EVP_PKEY_get_default_digest_nid.pod
DEPEND[man/man3/EVP_PKEY_get_default_digest_nid.3]=man3/EVP_PKEY_get_default_digest_nid.pod
GENERATE[man/man3/EVP_PKEY_get_default_digest_nid.3]=man3/EVP_PKEY_get_default_digest_nid.pod
DEPEND[html/man3/EVP_PKEY_get_field_type.html]=man3/EVP_PKEY_get_field_type.pod
GENERATE[html/man3/EVP_PKEY_get_field_type.html]=man3/EVP_PKEY_get_field_type.pod
DEPEND[man/man3/EVP_PKEY_get_field_type.3]=man3/EVP_PKEY_get_field_type.pod
GENERATE[man/man3/EVP_PKEY_get_field_type.3]=man3/EVP_PKEY_get_field_type.pod
DEPEND[html/man3/EVP_PKEY_get_group_name.html]=man3/EVP_PKEY_get_group_name.pod
GENERATE[html/man3/EVP_PKEY_get_group_name.html]=man3/EVP_PKEY_get_group_name.pod
DEPEND[man/man3/EVP_PKEY_get_group_name.3]=man3/EVP_PKEY_get_group_name.pod
GENERATE[man/man3/EVP_PKEY_get_group_name.3]=man3/EVP_PKEY_get_group_name.pod
DEPEND[html/man3/EVP_PKEY_get_size.html]=man3/EVP_PKEY_get_size.pod
GENERATE[html/man3/EVP_PKEY_get_size.html]=man3/EVP_PKEY_get_size.pod
DEPEND[man/man3/EVP_PKEY_get_size.3]=man3/EVP_PKEY_get_size.pod
GENERATE[man/man3/EVP_PKEY_get_size.3]=man3/EVP_PKEY_get_size.pod
DEPEND[html/man3/EVP_PKEY_gettable_params.html]=man3/EVP_PKEY_gettable_params.pod
GENERATE[html/man3/EVP_PKEY_gettable_params.html]=man3/EVP_PKEY_gettable_params.pod
DEPEND[man/man3/EVP_PKEY_gettable_params.3]=man3/EVP_PKEY_gettable_params.pod
GENERATE[man/man3/EVP_PKEY_gettable_params.3]=man3/EVP_PKEY_gettable_params.pod
DEPEND[html/man3/EVP_PKEY_is_a.html]=man3/EVP_PKEY_is_a.pod
GENERATE[html/man3/EVP_PKEY_is_a.html]=man3/EVP_PKEY_is_a.pod
DEPEND[man/man3/EVP_PKEY_is_a.3]=man3/EVP_PKEY_is_a.pod
GENERATE[man/man3/EVP_PKEY_is_a.3]=man3/EVP_PKEY_is_a.pod
DEPEND[html/man3/EVP_PKEY_keygen.html]=man3/EVP_PKEY_keygen.pod
GENERATE[html/man3/EVP_PKEY_keygen.html]=man3/EVP_PKEY_keygen.pod
DEPEND[man/man3/EVP_PKEY_keygen.3]=man3/EVP_PKEY_keygen.pod
GENERATE[man/man3/EVP_PKEY_keygen.3]=man3/EVP_PKEY_keygen.pod
DEPEND[html/man3/EVP_PKEY_meth_get_count.html]=man3/EVP_PKEY_meth_get_count.pod
GENERATE[html/man3/EVP_PKEY_meth_get_count.html]=man3/EVP_PKEY_meth_get_count.pod
DEPEND[man/man3/EVP_PKEY_meth_get_count.3]=man3/EVP_PKEY_meth_get_count.pod
GENERATE[man/man3/EVP_PKEY_meth_get_count.3]=man3/EVP_PKEY_meth_get_count.pod
DEPEND[html/man3/EVP_PKEY_meth_new.html]=man3/EVP_PKEY_meth_new.pod
GENERATE[html/man3/EVP_PKEY_meth_new.html]=man3/EVP_PKEY_meth_new.pod
DEPEND[man/man3/EVP_PKEY_meth_new.3]=man3/EVP_PKEY_meth_new.pod
GENERATE[man/man3/EVP_PKEY_meth_new.3]=man3/EVP_PKEY_meth_new.pod
DEPEND[html/man3/EVP_PKEY_new.html]=man3/EVP_PKEY_new.pod
GENERATE[html/man3/EVP_PKEY_new.html]=man3/EVP_PKEY_new.pod
DEPEND[man/man3/EVP_PKEY_new.3]=man3/EVP_PKEY_new.pod
GENERATE[man/man3/EVP_PKEY_new.3]=man3/EVP_PKEY_new.pod
DEPEND[html/man3/EVP_PKEY_print_private.html]=man3/EVP_PKEY_print_private.pod
GENERATE[html/man3/EVP_PKEY_print_private.html]=man3/EVP_PKEY_print_private.pod
DEPEND[man/man3/EVP_PKEY_print_private.3]=man3/EVP_PKEY_print_private.pod
GENERATE[man/man3/EVP_PKEY_print_private.3]=man3/EVP_PKEY_print_private.pod
DEPEND[html/man3/EVP_PKEY_set1_RSA.html]=man3/EVP_PKEY_set1_RSA.pod
GENERATE[html/man3/EVP_PKEY_set1_RSA.html]=man3/EVP_PKEY_set1_RSA.pod
DEPEND[man/man3/EVP_PKEY_set1_RSA.3]=man3/EVP_PKEY_set1_RSA.pod
GENERATE[man/man3/EVP_PKEY_set1_RSA.3]=man3/EVP_PKEY_set1_RSA.pod
DEPEND[html/man3/EVP_PKEY_set1_encoded_public_key.html]=man3/EVP_PKEY_set1_encoded_public_key.pod
GENERATE[html/man3/EVP_PKEY_set1_encoded_public_key.html]=man3/EVP_PKEY_set1_encoded_public_key.pod
DEPEND[man/man3/EVP_PKEY_set1_encoded_public_key.3]=man3/EVP_PKEY_set1_encoded_public_key.pod
GENERATE[man/man3/EVP_PKEY_set1_encoded_public_key.3]=man3/EVP_PKEY_set1_encoded_public_key.pod
DEPEND[html/man3/EVP_PKEY_set_type.html]=man3/EVP_PKEY_set_type.pod
GENERATE[html/man3/EVP_PKEY_set_type.html]=man3/EVP_PKEY_set_type.pod
DEPEND[man/man3/EVP_PKEY_set_type.3]=man3/EVP_PKEY_set_type.pod
GENERATE[man/man3/EVP_PKEY_set_type.3]=man3/EVP_PKEY_set_type.pod
DEPEND[html/man3/EVP_PKEY_settable_params.html]=man3/EVP_PKEY_settable_params.pod
GENERATE[html/man3/EVP_PKEY_settable_params.html]=man3/EVP_PKEY_settable_params.pod
DEPEND[man/man3/EVP_PKEY_settable_params.3]=man3/EVP_PKEY_settable_params.pod
GENERATE[man/man3/EVP_PKEY_settable_params.3]=man3/EVP_PKEY_settable_params.pod
DEPEND[html/man3/EVP_PKEY_sign.html]=man3/EVP_PKEY_sign.pod
GENERATE[html/man3/EVP_PKEY_sign.html]=man3/EVP_PKEY_sign.pod
DEPEND[man/man3/EVP_PKEY_sign.3]=man3/EVP_PKEY_sign.pod
GENERATE[man/man3/EVP_PKEY_sign.3]=man3/EVP_PKEY_sign.pod
DEPEND[html/man3/EVP_PKEY_todata.html]=man3/EVP_PKEY_todata.pod
GENERATE[html/man3/EVP_PKEY_todata.html]=man3/EVP_PKEY_todata.pod
DEPEND[man/man3/EVP_PKEY_todata.3]=man3/EVP_PKEY_todata.pod
GENERATE[man/man3/EVP_PKEY_todata.3]=man3/EVP_PKEY_todata.pod
DEPEND[html/man3/EVP_PKEY_verify.html]=man3/EVP_PKEY_verify.pod
GENERATE[html/man3/EVP_PKEY_verify.html]=man3/EVP_PKEY_verify.pod
DEPEND[man/man3/EVP_PKEY_verify.3]=man3/EVP_PKEY_verify.pod
GENERATE[man/man3/EVP_PKEY_verify.3]=man3/EVP_PKEY_verify.pod
DEPEND[html/man3/EVP_PKEY_verify_recover.html]=man3/EVP_PKEY_verify_recover.pod
GENERATE[html/man3/EVP_PKEY_verify_recover.html]=man3/EVP_PKEY_verify_recover.pod
DEPEND[man/man3/EVP_PKEY_verify_recover.3]=man3/EVP_PKEY_verify_recover.pod
GENERATE[man/man3/EVP_PKEY_verify_recover.3]=man3/EVP_PKEY_verify_recover.pod
DEPEND[html/man3/EVP_RAND.html]=man3/EVP_RAND.pod
GENERATE[html/man3/EVP_RAND.html]=man3/EVP_RAND.pod
DEPEND[man/man3/EVP_RAND.3]=man3/EVP_RAND.pod
GENERATE[man/man3/EVP_RAND.3]=man3/EVP_RAND.pod
DEPEND[html/man3/EVP_SIGNATURE.html]=man3/EVP_SIGNATURE.pod
GENERATE[html/man3/EVP_SIGNATURE.html]=man3/EVP_SIGNATURE.pod
DEPEND[man/man3/EVP_SIGNATURE.3]=man3/EVP_SIGNATURE.pod
GENERATE[man/man3/EVP_SIGNATURE.3]=man3/EVP_SIGNATURE.pod
DEPEND[html/man3/EVP_SealInit.html]=man3/EVP_SealInit.pod
GENERATE[html/man3/EVP_SealInit.html]=man3/EVP_SealInit.pod
DEPEND[man/man3/EVP_SealInit.3]=man3/EVP_SealInit.pod
GENERATE[man/man3/EVP_SealInit.3]=man3/EVP_SealInit.pod
DEPEND[html/man3/EVP_SignInit.html]=man3/EVP_SignInit.pod
GENERATE[html/man3/EVP_SignInit.html]=man3/EVP_SignInit.pod
DEPEND[man/man3/EVP_SignInit.3]=man3/EVP_SignInit.pod
GENERATE[man/man3/EVP_SignInit.3]=man3/EVP_SignInit.pod
DEPEND[html/man3/EVP_VerifyInit.html]=man3/EVP_VerifyInit.pod
GENERATE[html/man3/EVP_VerifyInit.html]=man3/EVP_VerifyInit.pod
DEPEND[man/man3/EVP_VerifyInit.3]=man3/EVP_VerifyInit.pod
GENERATE[man/man3/EVP_VerifyInit.3]=man3/EVP_VerifyInit.pod
DEPEND[html/man3/EVP_aes_128_gcm.html]=man3/EVP_aes_128_gcm.pod
GENERATE[html/man3/EVP_aes_128_gcm.html]=man3/EVP_aes_128_gcm.pod
DEPEND[man/man3/EVP_aes_128_gcm.3]=man3/EVP_aes_128_gcm.pod
GENERATE[man/man3/EVP_aes_128_gcm.3]=man3/EVP_aes_128_gcm.pod
DEPEND[html/man3/EVP_aria_128_gcm.html]=man3/EVP_aria_128_gcm.pod
GENERATE[html/man3/EVP_aria_128_gcm.html]=man3/EVP_aria_128_gcm.pod
DEPEND[man/man3/EVP_aria_128_gcm.3]=man3/EVP_aria_128_gcm.pod
GENERATE[man/man3/EVP_aria_128_gcm.3]=man3/EVP_aria_128_gcm.pod
DEPEND[html/man3/EVP_bf_cbc.html]=man3/EVP_bf_cbc.pod
GENERATE[html/man3/EVP_bf_cbc.html]=man3/EVP_bf_cbc.pod
DEPEND[man/man3/EVP_bf_cbc.3]=man3/EVP_bf_cbc.pod
GENERATE[man/man3/EVP_bf_cbc.3]=man3/EVP_bf_cbc.pod
DEPEND[html/man3/EVP_blake2b512.html]=man3/EVP_blake2b512.pod
GENERATE[html/man3/EVP_blake2b512.html]=man3/EVP_blake2b512.pod
DEPEND[man/man3/EVP_blake2b512.3]=man3/EVP_blake2b512.pod
GENERATE[man/man3/EVP_blake2b512.3]=man3/EVP_blake2b512.pod
DEPEND[html/man3/EVP_camellia_128_ecb.html]=man3/EVP_camellia_128_ecb.pod
GENERATE[html/man3/EVP_camellia_128_ecb.html]=man3/EVP_camellia_128_ecb.pod
DEPEND[man/man3/EVP_camellia_128_ecb.3]=man3/EVP_camellia_128_ecb.pod
GENERATE[man/man3/EVP_camellia_128_ecb.3]=man3/EVP_camellia_128_ecb.pod
DEPEND[html/man3/EVP_cast5_cbc.html]=man3/EVP_cast5_cbc.pod
GENERATE[html/man3/EVP_cast5_cbc.html]=man3/EVP_cast5_cbc.pod
DEPEND[man/man3/EVP_cast5_cbc.3]=man3/EVP_cast5_cbc.pod
GENERATE[man/man3/EVP_cast5_cbc.3]=man3/EVP_cast5_cbc.pod
DEPEND[html/man3/EVP_chacha20.html]=man3/EVP_chacha20.pod
GENERATE[html/man3/EVP_chacha20.html]=man3/EVP_chacha20.pod
DEPEND[man/man3/EVP_chacha20.3]=man3/EVP_chacha20.pod
GENERATE[man/man3/EVP_chacha20.3]=man3/EVP_chacha20.pod
DEPEND[html/man3/EVP_des_cbc.html]=man3/EVP_des_cbc.pod
GENERATE[html/man3/EVP_des_cbc.html]=man3/EVP_des_cbc.pod
DEPEND[man/man3/EVP_des_cbc.3]=man3/EVP_des_cbc.pod
GENERATE[man/man3/EVP_des_cbc.3]=man3/EVP_des_cbc.pod
DEPEND[html/man3/EVP_desx_cbc.html]=man3/EVP_desx_cbc.pod
GENERATE[html/man3/EVP_desx_cbc.html]=man3/EVP_desx_cbc.pod
DEPEND[man/man3/EVP_desx_cbc.3]=man3/EVP_desx_cbc.pod
GENERATE[man/man3/EVP_desx_cbc.3]=man3/EVP_desx_cbc.pod
DEPEND[html/man3/EVP_idea_cbc.html]=man3/EVP_idea_cbc.pod
GENERATE[html/man3/EVP_idea_cbc.html]=man3/EVP_idea_cbc.pod
DEPEND[man/man3/EVP_idea_cbc.3]=man3/EVP_idea_cbc.pod
GENERATE[man/man3/EVP_idea_cbc.3]=man3/EVP_idea_cbc.pod
DEPEND[html/man3/EVP_md2.html]=man3/EVP_md2.pod
GENERATE[html/man3/EVP_md2.html]=man3/EVP_md2.pod
DEPEND[man/man3/EVP_md2.3]=man3/EVP_md2.pod
GENERATE[man/man3/EVP_md2.3]=man3/EVP_md2.pod
DEPEND[html/man3/EVP_md4.html]=man3/EVP_md4.pod
GENERATE[html/man3/EVP_md4.html]=man3/EVP_md4.pod
DEPEND[man/man3/EVP_md4.3]=man3/EVP_md4.pod
GENERATE[man/man3/EVP_md4.3]=man3/EVP_md4.pod
DEPEND[html/man3/EVP_md5.html]=man3/EVP_md5.pod
GENERATE[html/man3/EVP_md5.html]=man3/EVP_md5.pod
DEPEND[man/man3/EVP_md5.3]=man3/EVP_md5.pod
GENERATE[man/man3/EVP_md5.3]=man3/EVP_md5.pod
DEPEND[html/man3/EVP_mdc2.html]=man3/EVP_mdc2.pod
GENERATE[html/man3/EVP_mdc2.html]=man3/EVP_mdc2.pod
DEPEND[man/man3/EVP_mdc2.3]=man3/EVP_mdc2.pod
GENERATE[man/man3/EVP_mdc2.3]=man3/EVP_mdc2.pod
DEPEND[html/man3/EVP_rc2_cbc.html]=man3/EVP_rc2_cbc.pod
GENERATE[html/man3/EVP_rc2_cbc.html]=man3/EVP_rc2_cbc.pod
DEPEND[man/man3/EVP_rc2_cbc.3]=man3/EVP_rc2_cbc.pod
GENERATE[man/man3/EVP_rc2_cbc.3]=man3/EVP_rc2_cbc.pod
DEPEND[html/man3/EVP_rc4.html]=man3/EVP_rc4.pod
GENERATE[html/man3/EVP_rc4.html]=man3/EVP_rc4.pod
DEPEND[man/man3/EVP_rc4.3]=man3/EVP_rc4.pod
GENERATE[man/man3/EVP_rc4.3]=man3/EVP_rc4.pod
DEPEND[html/man3/EVP_rc5_32_12_16_cbc.html]=man3/EVP_rc5_32_12_16_cbc.pod
GENERATE[html/man3/EVP_rc5_32_12_16_cbc.html]=man3/EVP_rc5_32_12_16_cbc.pod
DEPEND[man/man3/EVP_rc5_32_12_16_cbc.3]=man3/EVP_rc5_32_12_16_cbc.pod
GENERATE[man/man3/EVP_rc5_32_12_16_cbc.3]=man3/EVP_rc5_32_12_16_cbc.pod
DEPEND[html/man3/EVP_ripemd160.html]=man3/EVP_ripemd160.pod
GENERATE[html/man3/EVP_ripemd160.html]=man3/EVP_ripemd160.pod
DEPEND[man/man3/EVP_ripemd160.3]=man3/EVP_ripemd160.pod
GENERATE[man/man3/EVP_ripemd160.3]=man3/EVP_ripemd160.pod
DEPEND[html/man3/EVP_seed_cbc.html]=man3/EVP_seed_cbc.pod
GENERATE[html/man3/EVP_seed_cbc.html]=man3/EVP_seed_cbc.pod
DEPEND[man/man3/EVP_seed_cbc.3]=man3/EVP_seed_cbc.pod
GENERATE[man/man3/EVP_seed_cbc.3]=man3/EVP_seed_cbc.pod
DEPEND[html/man3/EVP_set_default_properties.html]=man3/EVP_set_default_properties.pod
GENERATE[html/man3/EVP_set_default_properties.html]=man3/EVP_set_default_properties.pod
DEPEND[man/man3/EVP_set_default_properties.3]=man3/EVP_set_default_properties.pod
GENERATE[man/man3/EVP_set_default_properties.3]=man3/EVP_set_default_properties.pod
DEPEND[html/man3/EVP_sha1.html]=man3/EVP_sha1.pod
GENERATE[html/man3/EVP_sha1.html]=man3/EVP_sha1.pod
DEPEND[man/man3/EVP_sha1.3]=man3/EVP_sha1.pod
GENERATE[man/man3/EVP_sha1.3]=man3/EVP_sha1.pod
DEPEND[html/man3/EVP_sha224.html]=man3/EVP_sha224.pod
GENERATE[html/man3/EVP_sha224.html]=man3/EVP_sha224.pod
DEPEND[man/man3/EVP_sha224.3]=man3/EVP_sha224.pod
GENERATE[man/man3/EVP_sha224.3]=man3/EVP_sha224.pod
DEPEND[html/man3/EVP_sha3_224.html]=man3/EVP_sha3_224.pod
GENERATE[html/man3/EVP_sha3_224.html]=man3/EVP_sha3_224.pod
DEPEND[man/man3/EVP_sha3_224.3]=man3/EVP_sha3_224.pod
GENERATE[man/man3/EVP_sha3_224.3]=man3/EVP_sha3_224.pod
DEPEND[html/man3/EVP_sm3.html]=man3/EVP_sm3.pod
GENERATE[html/man3/EVP_sm3.html]=man3/EVP_sm3.pod
DEPEND[man/man3/EVP_sm3.3]=man3/EVP_sm3.pod
GENERATE[man/man3/EVP_sm3.3]=man3/EVP_sm3.pod
DEPEND[html/man3/EVP_sm4_cbc.html]=man3/EVP_sm4_cbc.pod
GENERATE[html/man3/EVP_sm4_cbc.html]=man3/EVP_sm4_cbc.pod
DEPEND[man/man3/EVP_sm4_cbc.3]=man3/EVP_sm4_cbc.pod
GENERATE[man/man3/EVP_sm4_cbc.3]=man3/EVP_sm4_cbc.pod
DEPEND[html/man3/EVP_whirlpool.html]=man3/EVP_whirlpool.pod
GENERATE[html/man3/EVP_whirlpool.html]=man3/EVP_whirlpool.pod
DEPEND[man/man3/EVP_whirlpool.3]=man3/EVP_whirlpool.pod
GENERATE[man/man3/EVP_whirlpool.3]=man3/EVP_whirlpool.pod
DEPEND[html/man3/HMAC.html]=man3/HMAC.pod
GENERATE[html/man3/HMAC.html]=man3/HMAC.pod
DEPEND[man/man3/HMAC.3]=man3/HMAC.pod
GENERATE[man/man3/HMAC.3]=man3/HMAC.pod
DEPEND[html/man3/MD5.html]=man3/MD5.pod
GENERATE[html/man3/MD5.html]=man3/MD5.pod
DEPEND[man/man3/MD5.3]=man3/MD5.pod
GENERATE[man/man3/MD5.3]=man3/MD5.pod
DEPEND[html/man3/MDC2_Init.html]=man3/MDC2_Init.pod
GENERATE[html/man3/MDC2_Init.html]=man3/MDC2_Init.pod
DEPEND[man/man3/MDC2_Init.3]=man3/MDC2_Init.pod
GENERATE[man/man3/MDC2_Init.3]=man3/MDC2_Init.pod
DEPEND[html/man3/NCONF_new_ex.html]=man3/NCONF_new_ex.pod
GENERATE[html/man3/NCONF_new_ex.html]=man3/NCONF_new_ex.pod
DEPEND[man/man3/NCONF_new_ex.3]=man3/NCONF_new_ex.pod
GENERATE[man/man3/NCONF_new_ex.3]=man3/NCONF_new_ex.pod
DEPEND[html/man3/OBJ_nid2obj.html]=man3/OBJ_nid2obj.pod
GENERATE[html/man3/OBJ_nid2obj.html]=man3/OBJ_nid2obj.pod
DEPEND[man/man3/OBJ_nid2obj.3]=man3/OBJ_nid2obj.pod
GENERATE[man/man3/OBJ_nid2obj.3]=man3/OBJ_nid2obj.pod
DEPEND[html/man3/OCSP_REQUEST_new.html]=man3/OCSP_REQUEST_new.pod
GENERATE[html/man3/OCSP_REQUEST_new.html]=man3/OCSP_REQUEST_new.pod
DEPEND[man/man3/OCSP_REQUEST_new.3]=man3/OCSP_REQUEST_new.pod
GENERATE[man/man3/OCSP_REQUEST_new.3]=man3/OCSP_REQUEST_new.pod
DEPEND[html/man3/OCSP_cert_to_id.html]=man3/OCSP_cert_to_id.pod
GENERATE[html/man3/OCSP_cert_to_id.html]=man3/OCSP_cert_to_id.pod
DEPEND[man/man3/OCSP_cert_to_id.3]=man3/OCSP_cert_to_id.pod
GENERATE[man/man3/OCSP_cert_to_id.3]=man3/OCSP_cert_to_id.pod
DEPEND[html/man3/OCSP_request_add1_nonce.html]=man3/OCSP_request_add1_nonce.pod
GENERATE[html/man3/OCSP_request_add1_nonce.html]=man3/OCSP_request_add1_nonce.pod
DEPEND[man/man3/OCSP_request_add1_nonce.3]=man3/OCSP_request_add1_nonce.pod
GENERATE[man/man3/OCSP_request_add1_nonce.3]=man3/OCSP_request_add1_nonce.pod
DEPEND[html/man3/OCSP_resp_find_status.html]=man3/OCSP_resp_find_status.pod
GENERATE[html/man3/OCSP_resp_find_status.html]=man3/OCSP_resp_find_status.pod
DEPEND[man/man3/OCSP_resp_find_status.3]=man3/OCSP_resp_find_status.pod
GENERATE[man/man3/OCSP_resp_find_status.3]=man3/OCSP_resp_find_status.pod
DEPEND[html/man3/OCSP_response_status.html]=man3/OCSP_response_status.pod
GENERATE[html/man3/OCSP_response_status.html]=man3/OCSP_response_status.pod
DEPEND[man/man3/OCSP_response_status.3]=man3/OCSP_response_status.pod
GENERATE[man/man3/OCSP_response_status.3]=man3/OCSP_response_status.pod
DEPEND[html/man3/OCSP_sendreq_new.html]=man3/OCSP_sendreq_new.pod
GENERATE[html/man3/OCSP_sendreq_new.html]=man3/OCSP_sendreq_new.pod
DEPEND[man/man3/OCSP_sendreq_new.3]=man3/OCSP_sendreq_new.pod
GENERATE[man/man3/OCSP_sendreq_new.3]=man3/OCSP_sendreq_new.pod
DEPEND[html/man3/OPENSSL_Applink.html]=man3/OPENSSL_Applink.pod
GENERATE[html/man3/OPENSSL_Applink.html]=man3/OPENSSL_Applink.pod
DEPEND[man/man3/OPENSSL_Applink.3]=man3/OPENSSL_Applink.pod
GENERATE[man/man3/OPENSSL_Applink.3]=man3/OPENSSL_Applink.pod
DEPEND[html/man3/OPENSSL_FILE.html]=man3/OPENSSL_FILE.pod
GENERATE[html/man3/OPENSSL_FILE.html]=man3/OPENSSL_FILE.pod
DEPEND[man/man3/OPENSSL_FILE.3]=man3/OPENSSL_FILE.pod
GENERATE[man/man3/OPENSSL_FILE.3]=man3/OPENSSL_FILE.pod
DEPEND[html/man3/OPENSSL_LH_COMPFUNC.html]=man3/OPENSSL_LH_COMPFUNC.pod
GENERATE[html/man3/OPENSSL_LH_COMPFUNC.html]=man3/OPENSSL_LH_COMPFUNC.pod
DEPEND[man/man3/OPENSSL_LH_COMPFUNC.3]=man3/OPENSSL_LH_COMPFUNC.pod
GENERATE[man/man3/OPENSSL_LH_COMPFUNC.3]=man3/OPENSSL_LH_COMPFUNC.pod
DEPEND[html/man3/OPENSSL_LH_stats.html]=man3/OPENSSL_LH_stats.pod
GENERATE[html/man3/OPENSSL_LH_stats.html]=man3/OPENSSL_LH_stats.pod
DEPEND[man/man3/OPENSSL_LH_stats.3]=man3/OPENSSL_LH_stats.pod
GENERATE[man/man3/OPENSSL_LH_stats.3]=man3/OPENSSL_LH_stats.pod
DEPEND[html/man3/OPENSSL_config.html]=man3/OPENSSL_config.pod
GENERATE[html/man3/OPENSSL_config.html]=man3/OPENSSL_config.pod
DEPEND[man/man3/OPENSSL_config.3]=man3/OPENSSL_config.pod
GENERATE[man/man3/OPENSSL_config.3]=man3/OPENSSL_config.pod
DEPEND[html/man3/OPENSSL_fork_prepare.html]=man3/OPENSSL_fork_prepare.pod
GENERATE[html/man3/OPENSSL_fork_prepare.html]=man3/OPENSSL_fork_prepare.pod
DEPEND[man/man3/OPENSSL_fork_prepare.3]=man3/OPENSSL_fork_prepare.pod
GENERATE[man/man3/OPENSSL_fork_prepare.3]=man3/OPENSSL_fork_prepare.pod
DEPEND[html/man3/OPENSSL_gmtime.html]=man3/OPENSSL_gmtime.pod
GENERATE[html/man3/OPENSSL_gmtime.html]=man3/OPENSSL_gmtime.pod
DEPEND[man/man3/OPENSSL_gmtime.3]=man3/OPENSSL_gmtime.pod
GENERATE[man/man3/OPENSSL_gmtime.3]=man3/OPENSSL_gmtime.pod
DEPEND[html/man3/OPENSSL_hexchar2int.html]=man3/OPENSSL_hexchar2int.pod
GENERATE[html/man3/OPENSSL_hexchar2int.html]=man3/OPENSSL_hexchar2int.pod
DEPEND[man/man3/OPENSSL_hexchar2int.3]=man3/OPENSSL_hexchar2int.pod
GENERATE[man/man3/OPENSSL_hexchar2int.3]=man3/OPENSSL_hexchar2int.pod
DEPEND[html/man3/OPENSSL_ia32cap.html]=man3/OPENSSL_ia32cap.pod
GENERATE[html/man3/OPENSSL_ia32cap.html]=man3/OPENSSL_ia32cap.pod
DEPEND[man/man3/OPENSSL_ia32cap.3]=man3/OPENSSL_ia32cap.pod
GENERATE[man/man3/OPENSSL_ia32cap.3]=man3/OPENSSL_ia32cap.pod
DEPEND[html/man3/OPENSSL_init_crypto.html]=man3/OPENSSL_init_crypto.pod
GENERATE[html/man3/OPENSSL_init_crypto.html]=man3/OPENSSL_init_crypto.pod
DEPEND[man/man3/OPENSSL_init_crypto.3]=man3/OPENSSL_init_crypto.pod
GENERATE[man/man3/OPENSSL_init_crypto.3]=man3/OPENSSL_init_crypto.pod
DEPEND[html/man3/OPENSSL_init_ssl.html]=man3/OPENSSL_init_ssl.pod
GENERATE[html/man3/OPENSSL_init_ssl.html]=man3/OPENSSL_init_ssl.pod
DEPEND[man/man3/OPENSSL_init_ssl.3]=man3/OPENSSL_init_ssl.pod
GENERATE[man/man3/OPENSSL_init_ssl.3]=man3/OPENSSL_init_ssl.pod
DEPEND[html/man3/OPENSSL_instrument_bus.html]=man3/OPENSSL_instrument_bus.pod
GENERATE[html/man3/OPENSSL_instrument_bus.html]=man3/OPENSSL_instrument_bus.pod
DEPEND[man/man3/OPENSSL_instrument_bus.3]=man3/OPENSSL_instrument_bus.pod
GENERATE[man/man3/OPENSSL_instrument_bus.3]=man3/OPENSSL_instrument_bus.pod
DEPEND[html/man3/OPENSSL_load_builtin_modules.html]=man3/OPENSSL_load_builtin_modules.pod
GENERATE[html/man3/OPENSSL_load_builtin_modules.html]=man3/OPENSSL_load_builtin_modules.pod
DEPEND[man/man3/OPENSSL_load_builtin_modules.3]=man3/OPENSSL_load_builtin_modules.pod
GENERATE[man/man3/OPENSSL_load_builtin_modules.3]=man3/OPENSSL_load_builtin_modules.pod
DEPEND[html/man3/OPENSSL_malloc.html]=man3/OPENSSL_malloc.pod
GENERATE[html/man3/OPENSSL_malloc.html]=man3/OPENSSL_malloc.pod
DEPEND[man/man3/OPENSSL_malloc.3]=man3/OPENSSL_malloc.pod
GENERATE[man/man3/OPENSSL_malloc.3]=man3/OPENSSL_malloc.pod
DEPEND[html/man3/OPENSSL_s390xcap.html]=man3/OPENSSL_s390xcap.pod
GENERATE[html/man3/OPENSSL_s390xcap.html]=man3/OPENSSL_s390xcap.pod
DEPEND[man/man3/OPENSSL_s390xcap.3]=man3/OPENSSL_s390xcap.pod
GENERATE[man/man3/OPENSSL_s390xcap.3]=man3/OPENSSL_s390xcap.pod
DEPEND[html/man3/OPENSSL_secure_malloc.html]=man3/OPENSSL_secure_malloc.pod
GENERATE[html/man3/OPENSSL_secure_malloc.html]=man3/OPENSSL_secure_malloc.pod
DEPEND[man/man3/OPENSSL_secure_malloc.3]=man3/OPENSSL_secure_malloc.pod
GENERATE[man/man3/OPENSSL_secure_malloc.3]=man3/OPENSSL_secure_malloc.pod
DEPEND[html/man3/OPENSSL_strcasecmp.html]=man3/OPENSSL_strcasecmp.pod
GENERATE[html/man3/OPENSSL_strcasecmp.html]=man3/OPENSSL_strcasecmp.pod
DEPEND[man/man3/OPENSSL_strcasecmp.3]=man3/OPENSSL_strcasecmp.pod
GENERATE[man/man3/OPENSSL_strcasecmp.3]=man3/OPENSSL_strcasecmp.pod
DEPEND[html/man3/OSSL_ALGORITHM.html]=man3/OSSL_ALGORITHM.pod
GENERATE[html/man3/OSSL_ALGORITHM.html]=man3/OSSL_ALGORITHM.pod
DEPEND[man/man3/OSSL_ALGORITHM.3]=man3/OSSL_ALGORITHM.pod
GENERATE[man/man3/OSSL_ALGORITHM.3]=man3/OSSL_ALGORITHM.pod
DEPEND[html/man3/OSSL_CALLBACK.html]=man3/OSSL_CALLBACK.pod
GENERATE[html/man3/OSSL_CALLBACK.html]=man3/OSSL_CALLBACK.pod
DEPEND[man/man3/OSSL_CALLBACK.3]=man3/OSSL_CALLBACK.pod
GENERATE[man/man3/OSSL_CALLBACK.3]=man3/OSSL_CALLBACK.pod
DEPEND[html/man3/OSSL_CMP_CTX_new.html]=man3/OSSL_CMP_CTX_new.pod
GENERATE[html/man3/OSSL_CMP_CTX_new.html]=man3/OSSL_CMP_CTX_new.pod
DEPEND[man/man3/OSSL_CMP_CTX_new.3]=man3/OSSL_CMP_CTX_new.pod
GENERATE[man/man3/OSSL_CMP_CTX_new.3]=man3/OSSL_CMP_CTX_new.pod
DEPEND[html/man3/OSSL_CMP_HDR_get0_transactionID.html]=man3/OSSL_CMP_HDR_get0_transactionID.pod
GENERATE[html/man3/OSSL_CMP_HDR_get0_transactionID.html]=man3/OSSL_CMP_HDR_get0_transactionID.pod
DEPEND[man/man3/OSSL_CMP_HDR_get0_transactionID.3]=man3/OSSL_CMP_HDR_get0_transactionID.pod
GENERATE[man/man3/OSSL_CMP_HDR_get0_transactionID.3]=man3/OSSL_CMP_HDR_get0_transactionID.pod
DEPEND[html/man3/OSSL_CMP_ITAV_set0.html]=man3/OSSL_CMP_ITAV_set0.pod
GENERATE[html/man3/OSSL_CMP_ITAV_set0.html]=man3/OSSL_CMP_ITAV_set0.pod
DEPEND[man/man3/OSSL_CMP_ITAV_set0.3]=man3/OSSL_CMP_ITAV_set0.pod
GENERATE[man/man3/OSSL_CMP_ITAV_set0.3]=man3/OSSL_CMP_ITAV_set0.pod
DEPEND[html/man3/OSSL_CMP_MSG_get0_header.html]=man3/OSSL_CMP_MSG_get0_header.pod
GENERATE[html/man3/OSSL_CMP_MSG_get0_header.html]=man3/OSSL_CMP_MSG_get0_header.pod
DEPEND[man/man3/OSSL_CMP_MSG_get0_header.3]=man3/OSSL_CMP_MSG_get0_header.pod
GENERATE[man/man3/OSSL_CMP_MSG_get0_header.3]=man3/OSSL_CMP_MSG_get0_header.pod
DEPEND[html/man3/OSSL_CMP_MSG_http_perform.html]=man3/OSSL_CMP_MSG_http_perform.pod
GENERATE[html/man3/OSSL_CMP_MSG_http_perform.html]=man3/OSSL_CMP_MSG_http_perform.pod
DEPEND[man/man3/OSSL_CMP_MSG_http_perform.3]=man3/OSSL_CMP_MSG_http_perform.pod
GENERATE[man/man3/OSSL_CMP_MSG_http_perform.3]=man3/OSSL_CMP_MSG_http_perform.pod
DEPEND[html/man3/OSSL_CMP_SRV_CTX_new.html]=man3/OSSL_CMP_SRV_CTX_new.pod
GENERATE[html/man3/OSSL_CMP_SRV_CTX_new.html]=man3/OSSL_CMP_SRV_CTX_new.pod
DEPEND[man/man3/OSSL_CMP_SRV_CTX_new.3]=man3/OSSL_CMP_SRV_CTX_new.pod
GENERATE[man/man3/OSSL_CMP_SRV_CTX_new.3]=man3/OSSL_CMP_SRV_CTX_new.pod
DEPEND[html/man3/OSSL_CMP_STATUSINFO_new.html]=man3/OSSL_CMP_STATUSINFO_new.pod
GENERATE[html/man3/OSSL_CMP_STATUSINFO_new.html]=man3/OSSL_CMP_STATUSINFO_new.pod
DEPEND[man/man3/OSSL_CMP_STATUSINFO_new.3]=man3/OSSL_CMP_STATUSINFO_new.pod
GENERATE[man/man3/OSSL_CMP_STATUSINFO_new.3]=man3/OSSL_CMP_STATUSINFO_new.pod
DEPEND[html/man3/OSSL_CMP_exec_certreq.html]=man3/OSSL_CMP_exec_certreq.pod
GENERATE[html/man3/OSSL_CMP_exec_certreq.html]=man3/OSSL_CMP_exec_certreq.pod
DEPEND[man/man3/OSSL_CMP_exec_certreq.3]=man3/OSSL_CMP_exec_certreq.pod
GENERATE[man/man3/OSSL_CMP_exec_certreq.3]=man3/OSSL_CMP_exec_certreq.pod
DEPEND[html/man3/OSSL_CMP_log_open.html]=man3/OSSL_CMP_log_open.pod
GENERATE[html/man3/OSSL_CMP_log_open.html]=man3/OSSL_CMP_log_open.pod
DEPEND[man/man3/OSSL_CMP_log_open.3]=man3/OSSL_CMP_log_open.pod
GENERATE[man/man3/OSSL_CMP_log_open.3]=man3/OSSL_CMP_log_open.pod
DEPEND[html/man3/OSSL_CMP_validate_msg.html]=man3/OSSL_CMP_validate_msg.pod
GENERATE[html/man3/OSSL_CMP_validate_msg.html]=man3/OSSL_CMP_validate_msg.pod
DEPEND[man/man3/OSSL_CMP_validate_msg.3]=man3/OSSL_CMP_validate_msg.pod
GENERATE[man/man3/OSSL_CMP_validate_msg.3]=man3/OSSL_CMP_validate_msg.pod
DEPEND[html/man3/OSSL_CORE_MAKE_FUNC.html]=man3/OSSL_CORE_MAKE_FUNC.pod
GENERATE[html/man3/OSSL_CORE_MAKE_FUNC.html]=man3/OSSL_CORE_MAKE_FUNC.pod
DEPEND[man/man3/OSSL_CORE_MAKE_FUNC.3]=man3/OSSL_CORE_MAKE_FUNC.pod
GENERATE[man/man3/OSSL_CORE_MAKE_FUNC.3]=man3/OSSL_CORE_MAKE_FUNC.pod
DEPEND[html/man3/OSSL_CRMF_MSG_get0_tmpl.html]=man3/OSSL_CRMF_MSG_get0_tmpl.pod
GENERATE[html/man3/OSSL_CRMF_MSG_get0_tmpl.html]=man3/OSSL_CRMF_MSG_get0_tmpl.pod
DEPEND[man/man3/OSSL_CRMF_MSG_get0_tmpl.3]=man3/OSSL_CRMF_MSG_get0_tmpl.pod
GENERATE[man/man3/OSSL_CRMF_MSG_get0_tmpl.3]=man3/OSSL_CRMF_MSG_get0_tmpl.pod
DEPEND[html/man3/OSSL_CRMF_MSG_set0_validity.html]=man3/OSSL_CRMF_MSG_set0_validity.pod
GENERATE[html/man3/OSSL_CRMF_MSG_set0_validity.html]=man3/OSSL_CRMF_MSG_set0_validity.pod
DEPEND[man/man3/OSSL_CRMF_MSG_set0_validity.3]=man3/OSSL_CRMF_MSG_set0_validity.pod
GENERATE[man/man3/OSSL_CRMF_MSG_set0_validity.3]=man3/OSSL_CRMF_MSG_set0_validity.pod
DEPEND[html/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.html]=man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod
GENERATE[html/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.html]=man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod
DEPEND[man/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.3]=man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod
GENERATE[man/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.3]=man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.pod
DEPEND[html/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.html]=man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod
GENERATE[html/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.html]=man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod
DEPEND[man/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.3]=man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod
GENERATE[man/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.3]=man3/OSSL_CRMF_MSG_set1_regInfo_certReq.pod
DEPEND[html/man3/OSSL_CRMF_pbmp_new.html]=man3/OSSL_CRMF_pbmp_new.pod
GENERATE[html/man3/OSSL_CRMF_pbmp_new.html]=man3/OSSL_CRMF_pbmp_new.pod
DEPEND[man/man3/OSSL_CRMF_pbmp_new.3]=man3/OSSL_CRMF_pbmp_new.pod
GENERATE[man/man3/OSSL_CRMF_pbmp_new.3]=man3/OSSL_CRMF_pbmp_new.pod
DEPEND[html/man3/OSSL_DECODER.html]=man3/OSSL_DECODER.pod
GENERATE[html/man3/OSSL_DECODER.html]=man3/OSSL_DECODER.pod
DEPEND[man/man3/OSSL_DECODER.3]=man3/OSSL_DECODER.pod
GENERATE[man/man3/OSSL_DECODER.3]=man3/OSSL_DECODER.pod
DEPEND[html/man3/OSSL_DECODER_CTX.html]=man3/OSSL_DECODER_CTX.pod
GENERATE[html/man3/OSSL_DECODER_CTX.html]=man3/OSSL_DECODER_CTX.pod
DEPEND[man/man3/OSSL_DECODER_CTX.3]=man3/OSSL_DECODER_CTX.pod
GENERATE[man/man3/OSSL_DECODER_CTX.3]=man3/OSSL_DECODER_CTX.pod
DEPEND[html/man3/OSSL_DECODER_CTX_new_for_pkey.html]=man3/OSSL_DECODER_CTX_new_for_pkey.pod
GENERATE[html/man3/OSSL_DECODER_CTX_new_for_pkey.html]=man3/OSSL_DECODER_CTX_new_for_pkey.pod
DEPEND[man/man3/OSSL_DECODER_CTX_new_for_pkey.3]=man3/OSSL_DECODER_CTX_new_for_pkey.pod
GENERATE[man/man3/OSSL_DECODER_CTX_new_for_pkey.3]=man3/OSSL_DECODER_CTX_new_for_pkey.pod
DEPEND[html/man3/OSSL_DECODER_from_bio.html]=man3/OSSL_DECODER_from_bio.pod
GENERATE[html/man3/OSSL_DECODER_from_bio.html]=man3/OSSL_DECODER_from_bio.pod
DEPEND[man/man3/OSSL_DECODER_from_bio.3]=man3/OSSL_DECODER_from_bio.pod
GENERATE[man/man3/OSSL_DECODER_from_bio.3]=man3/OSSL_DECODER_from_bio.pod
DEPEND[html/man3/OSSL_DISPATCH.html]=man3/OSSL_DISPATCH.pod
GENERATE[html/man3/OSSL_DISPATCH.html]=man3/OSSL_DISPATCH.pod
DEPEND[man/man3/OSSL_DISPATCH.3]=man3/OSSL_DISPATCH.pod
GENERATE[man/man3/OSSL_DISPATCH.3]=man3/OSSL_DISPATCH.pod
DEPEND[html/man3/OSSL_ENCODER.html]=man3/OSSL_ENCODER.pod
GENERATE[html/man3/OSSL_ENCODER.html]=man3/OSSL_ENCODER.pod
DEPEND[man/man3/OSSL_ENCODER.3]=man3/OSSL_ENCODER.pod
GENERATE[man/man3/OSSL_ENCODER.3]=man3/OSSL_ENCODER.pod
DEPEND[html/man3/OSSL_ENCODER_CTX.html]=man3/OSSL_ENCODER_CTX.pod
GENERATE[html/man3/OSSL_ENCODER_CTX.html]=man3/OSSL_ENCODER_CTX.pod
DEPEND[man/man3/OSSL_ENCODER_CTX.3]=man3/OSSL_ENCODER_CTX.pod
GENERATE[man/man3/OSSL_ENCODER_CTX.3]=man3/OSSL_ENCODER_CTX.pod
DEPEND[html/man3/OSSL_ENCODER_CTX_new_for_pkey.html]=man3/OSSL_ENCODER_CTX_new_for_pkey.pod
GENERATE[html/man3/OSSL_ENCODER_CTX_new_for_pkey.html]=man3/OSSL_ENCODER_CTX_new_for_pkey.pod
DEPEND[man/man3/OSSL_ENCODER_CTX_new_for_pkey.3]=man3/OSSL_ENCODER_CTX_new_for_pkey.pod
GENERATE[man/man3/OSSL_ENCODER_CTX_new_for_pkey.3]=man3/OSSL_ENCODER_CTX_new_for_pkey.pod
DEPEND[html/man3/OSSL_ENCODER_to_bio.html]=man3/OSSL_ENCODER_to_bio.pod
GENERATE[html/man3/OSSL_ENCODER_to_bio.html]=man3/OSSL_ENCODER_to_bio.pod
DEPEND[man/man3/OSSL_ENCODER_to_bio.3]=man3/OSSL_ENCODER_to_bio.pod
GENERATE[man/man3/OSSL_ENCODER_to_bio.3]=man3/OSSL_ENCODER_to_bio.pod
DEPEND[html/man3/OSSL_ESS_check_signing_certs.html]=man3/OSSL_ESS_check_signing_certs.pod
GENERATE[html/man3/OSSL_ESS_check_signing_certs.html]=man3/OSSL_ESS_check_signing_certs.pod
DEPEND[man/man3/OSSL_ESS_check_signing_certs.3]=man3/OSSL_ESS_check_signing_certs.pod
GENERATE[man/man3/OSSL_ESS_check_signing_certs.3]=man3/OSSL_ESS_check_signing_certs.pod
DEPEND[html/man3/OSSL_HTTP_REQ_CTX.html]=man3/OSSL_HTTP_REQ_CTX.pod
GENERATE[html/man3/OSSL_HTTP_REQ_CTX.html]=man3/OSSL_HTTP_REQ_CTX.pod
DEPEND[man/man3/OSSL_HTTP_REQ_CTX.3]=man3/OSSL_HTTP_REQ_CTX.pod
GENERATE[man/man3/OSSL_HTTP_REQ_CTX.3]=man3/OSSL_HTTP_REQ_CTX.pod
DEPEND[html/man3/OSSL_HTTP_parse_url.html]=man3/OSSL_HTTP_parse_url.pod
GENERATE[html/man3/OSSL_HTTP_parse_url.html]=man3/OSSL_HTTP_parse_url.pod
DEPEND[man/man3/OSSL_HTTP_parse_url.3]=man3/OSSL_HTTP_parse_url.pod
GENERATE[man/man3/OSSL_HTTP_parse_url.3]=man3/OSSL_HTTP_parse_url.pod
DEPEND[html/man3/OSSL_HTTP_transfer.html]=man3/OSSL_HTTP_transfer.pod
GENERATE[html/man3/OSSL_HTTP_transfer.html]=man3/OSSL_HTTP_transfer.pod
DEPEND[man/man3/OSSL_HTTP_transfer.3]=man3/OSSL_HTTP_transfer.pod
GENERATE[man/man3/OSSL_HTTP_transfer.3]=man3/OSSL_HTTP_transfer.pod
DEPEND[html/man3/OSSL_ITEM.html]=man3/OSSL_ITEM.pod
GENERATE[html/man3/OSSL_ITEM.html]=man3/OSSL_ITEM.pod
DEPEND[man/man3/OSSL_ITEM.3]=man3/OSSL_ITEM.pod
GENERATE[man/man3/OSSL_ITEM.3]=man3/OSSL_ITEM.pod
DEPEND[html/man3/OSSL_LIB_CTX.html]=man3/OSSL_LIB_CTX.pod
GENERATE[html/man3/OSSL_LIB_CTX.html]=man3/OSSL_LIB_CTX.pod
DEPEND[man/man3/OSSL_LIB_CTX.3]=man3/OSSL_LIB_CTX.pod
GENERATE[man/man3/OSSL_LIB_CTX.3]=man3/OSSL_LIB_CTX.pod
DEPEND[html/man3/OSSL_PARAM.html]=man3/OSSL_PARAM.pod
GENERATE[html/man3/OSSL_PARAM.html]=man3/OSSL_PARAM.pod
DEPEND[man/man3/OSSL_PARAM.3]=man3/OSSL_PARAM.pod
GENERATE[man/man3/OSSL_PARAM.3]=man3/OSSL_PARAM.pod
DEPEND[html/man3/OSSL_PARAM_BLD.html]=man3/OSSL_PARAM_BLD.pod
GENERATE[html/man3/OSSL_PARAM_BLD.html]=man3/OSSL_PARAM_BLD.pod
DEPEND[man/man3/OSSL_PARAM_BLD.3]=man3/OSSL_PARAM_BLD.pod
GENERATE[man/man3/OSSL_PARAM_BLD.3]=man3/OSSL_PARAM_BLD.pod
DEPEND[html/man3/OSSL_PARAM_allocate_from_text.html]=man3/OSSL_PARAM_allocate_from_text.pod
GENERATE[html/man3/OSSL_PARAM_allocate_from_text.html]=man3/OSSL_PARAM_allocate_from_text.pod
DEPEND[man/man3/OSSL_PARAM_allocate_from_text.3]=man3/OSSL_PARAM_allocate_from_text.pod
GENERATE[man/man3/OSSL_PARAM_allocate_from_text.3]=man3/OSSL_PARAM_allocate_from_text.pod
DEPEND[html/man3/OSSL_PARAM_dup.html]=man3/OSSL_PARAM_dup.pod
GENERATE[html/man3/OSSL_PARAM_dup.html]=man3/OSSL_PARAM_dup.pod
DEPEND[man/man3/OSSL_PARAM_dup.3]=man3/OSSL_PARAM_dup.pod
GENERATE[man/man3/OSSL_PARAM_dup.3]=man3/OSSL_PARAM_dup.pod
DEPEND[html/man3/OSSL_PARAM_int.html]=man3/OSSL_PARAM_int.pod
GENERATE[html/man3/OSSL_PARAM_int.html]=man3/OSSL_PARAM_int.pod
DEPEND[man/man3/OSSL_PARAM_int.3]=man3/OSSL_PARAM_int.pod
GENERATE[man/man3/OSSL_PARAM_int.3]=man3/OSSL_PARAM_int.pod
DEPEND[html/man3/OSSL_PROVIDER.html]=man3/OSSL_PROVIDER.pod
GENERATE[html/man3/OSSL_PROVIDER.html]=man3/OSSL_PROVIDER.pod
DEPEND[man/man3/OSSL_PROVIDER.3]=man3/OSSL_PROVIDER.pod
GENERATE[man/man3/OSSL_PROVIDER.3]=man3/OSSL_PROVIDER.pod
DEPEND[html/man3/OSSL_SELF_TEST_new.html]=man3/OSSL_SELF_TEST_new.pod
GENERATE[html/man3/OSSL_SELF_TEST_new.html]=man3/OSSL_SELF_TEST_new.pod
DEPEND[man/man3/OSSL_SELF_TEST_new.3]=man3/OSSL_SELF_TEST_new.pod
GENERATE[man/man3/OSSL_SELF_TEST_new.3]=man3/OSSL_SELF_TEST_new.pod
DEPEND[html/man3/OSSL_SELF_TEST_set_callback.html]=man3/OSSL_SELF_TEST_set_callback.pod
GENERATE[html/man3/OSSL_SELF_TEST_set_callback.html]=man3/OSSL_SELF_TEST_set_callback.pod
DEPEND[man/man3/OSSL_SELF_TEST_set_callback.3]=man3/OSSL_SELF_TEST_set_callback.pod
GENERATE[man/man3/OSSL_SELF_TEST_set_callback.3]=man3/OSSL_SELF_TEST_set_callback.pod
DEPEND[html/man3/OSSL_STORE_INFO.html]=man3/OSSL_STORE_INFO.pod
GENERATE[html/man3/OSSL_STORE_INFO.html]=man3/OSSL_STORE_INFO.pod
DEPEND[man/man3/OSSL_STORE_INFO.3]=man3/OSSL_STORE_INFO.pod
GENERATE[man/man3/OSSL_STORE_INFO.3]=man3/OSSL_STORE_INFO.pod
DEPEND[html/man3/OSSL_STORE_LOADER.html]=man3/OSSL_STORE_LOADER.pod
GENERATE[html/man3/OSSL_STORE_LOADER.html]=man3/OSSL_STORE_LOADER.pod
DEPEND[man/man3/OSSL_STORE_LOADER.3]=man3/OSSL_STORE_LOADER.pod
GENERATE[man/man3/OSSL_STORE_LOADER.3]=man3/OSSL_STORE_LOADER.pod
DEPEND[html/man3/OSSL_STORE_SEARCH.html]=man3/OSSL_STORE_SEARCH.pod
GENERATE[html/man3/OSSL_STORE_SEARCH.html]=man3/OSSL_STORE_SEARCH.pod
DEPEND[man/man3/OSSL_STORE_SEARCH.3]=man3/OSSL_STORE_SEARCH.pod
GENERATE[man/man3/OSSL_STORE_SEARCH.3]=man3/OSSL_STORE_SEARCH.pod
DEPEND[html/man3/OSSL_STORE_attach.html]=man3/OSSL_STORE_attach.pod
GENERATE[html/man3/OSSL_STORE_attach.html]=man3/OSSL_STORE_attach.pod
DEPEND[man/man3/OSSL_STORE_attach.3]=man3/OSSL_STORE_attach.pod
GENERATE[man/man3/OSSL_STORE_attach.3]=man3/OSSL_STORE_attach.pod
DEPEND[html/man3/OSSL_STORE_expect.html]=man3/OSSL_STORE_expect.pod
GENERATE[html/man3/OSSL_STORE_expect.html]=man3/OSSL_STORE_expect.pod
DEPEND[man/man3/OSSL_STORE_expect.3]=man3/OSSL_STORE_expect.pod
GENERATE[man/man3/OSSL_STORE_expect.3]=man3/OSSL_STORE_expect.pod
DEPEND[html/man3/OSSL_STORE_open.html]=man3/OSSL_STORE_open.pod
GENERATE[html/man3/OSSL_STORE_open.html]=man3/OSSL_STORE_open.pod
DEPEND[man/man3/OSSL_STORE_open.3]=man3/OSSL_STORE_open.pod
GENERATE[man/man3/OSSL_STORE_open.3]=man3/OSSL_STORE_open.pod
DEPEND[html/man3/OSSL_trace_enabled.html]=man3/OSSL_trace_enabled.pod
GENERATE[html/man3/OSSL_trace_enabled.html]=man3/OSSL_trace_enabled.pod
DEPEND[man/man3/OSSL_trace_enabled.3]=man3/OSSL_trace_enabled.pod
GENERATE[man/man3/OSSL_trace_enabled.3]=man3/OSSL_trace_enabled.pod
DEPEND[html/man3/OSSL_trace_get_category_num.html]=man3/OSSL_trace_get_category_num.pod
GENERATE[html/man3/OSSL_trace_get_category_num.html]=man3/OSSL_trace_get_category_num.pod
DEPEND[man/man3/OSSL_trace_get_category_num.3]=man3/OSSL_trace_get_category_num.pod
GENERATE[man/man3/OSSL_trace_get_category_num.3]=man3/OSSL_trace_get_category_num.pod
DEPEND[html/man3/OSSL_trace_set_channel.html]=man3/OSSL_trace_set_channel.pod
GENERATE[html/man3/OSSL_trace_set_channel.html]=man3/OSSL_trace_set_channel.pod
DEPEND[man/man3/OSSL_trace_set_channel.3]=man3/OSSL_trace_set_channel.pod
GENERATE[man/man3/OSSL_trace_set_channel.3]=man3/OSSL_trace_set_channel.pod
DEPEND[html/man3/OpenSSL_add_all_algorithms.html]=man3/OpenSSL_add_all_algorithms.pod
GENERATE[html/man3/OpenSSL_add_all_algorithms.html]=man3/OpenSSL_add_all_algorithms.pod
DEPEND[man/man3/OpenSSL_add_all_algorithms.3]=man3/OpenSSL_add_all_algorithms.pod
GENERATE[man/man3/OpenSSL_add_all_algorithms.3]=man3/OpenSSL_add_all_algorithms.pod
DEPEND[html/man3/OpenSSL_version.html]=man3/OpenSSL_version.pod
GENERATE[html/man3/OpenSSL_version.html]=man3/OpenSSL_version.pod
DEPEND[man/man3/OpenSSL_version.3]=man3/OpenSSL_version.pod
GENERATE[man/man3/OpenSSL_version.3]=man3/OpenSSL_version.pod
DEPEND[html/man3/PEM_X509_INFO_read_bio_ex.html]=man3/PEM_X509_INFO_read_bio_ex.pod
GENERATE[html/man3/PEM_X509_INFO_read_bio_ex.html]=man3/PEM_X509_INFO_read_bio_ex.pod
DEPEND[man/man3/PEM_X509_INFO_read_bio_ex.3]=man3/PEM_X509_INFO_read_bio_ex.pod
GENERATE[man/man3/PEM_X509_INFO_read_bio_ex.3]=man3/PEM_X509_INFO_read_bio_ex.pod
DEPEND[html/man3/PEM_bytes_read_bio.html]=man3/PEM_bytes_read_bio.pod
GENERATE[html/man3/PEM_bytes_read_bio.html]=man3/PEM_bytes_read_bio.pod
DEPEND[man/man3/PEM_bytes_read_bio.3]=man3/PEM_bytes_read_bio.pod
GENERATE[man/man3/PEM_bytes_read_bio.3]=man3/PEM_bytes_read_bio.pod
DEPEND[html/man3/PEM_read.html]=man3/PEM_read.pod
GENERATE[html/man3/PEM_read.html]=man3/PEM_read.pod
DEPEND[man/man3/PEM_read.3]=man3/PEM_read.pod
GENERATE[man/man3/PEM_read.3]=man3/PEM_read.pod
DEPEND[html/man3/PEM_read_CMS.html]=man3/PEM_read_CMS.pod
GENERATE[html/man3/PEM_read_CMS.html]=man3/PEM_read_CMS.pod
DEPEND[man/man3/PEM_read_CMS.3]=man3/PEM_read_CMS.pod
GENERATE[man/man3/PEM_read_CMS.3]=man3/PEM_read_CMS.pod
DEPEND[html/man3/PEM_read_bio_PrivateKey.html]=man3/PEM_read_bio_PrivateKey.pod
GENERATE[html/man3/PEM_read_bio_PrivateKey.html]=man3/PEM_read_bio_PrivateKey.pod
DEPEND[man/man3/PEM_read_bio_PrivateKey.3]=man3/PEM_read_bio_PrivateKey.pod
GENERATE[man/man3/PEM_read_bio_PrivateKey.3]=man3/PEM_read_bio_PrivateKey.pod
DEPEND[html/man3/PEM_read_bio_ex.html]=man3/PEM_read_bio_ex.pod
GENERATE[html/man3/PEM_read_bio_ex.html]=man3/PEM_read_bio_ex.pod
DEPEND[man/man3/PEM_read_bio_ex.3]=man3/PEM_read_bio_ex.pod
GENERATE[man/man3/PEM_read_bio_ex.3]=man3/PEM_read_bio_ex.pod
DEPEND[html/man3/PEM_write_bio_CMS_stream.html]=man3/PEM_write_bio_CMS_stream.pod
GENERATE[html/man3/PEM_write_bio_CMS_stream.html]=man3/PEM_write_bio_CMS_stream.pod
DEPEND[man/man3/PEM_write_bio_CMS_stream.3]=man3/PEM_write_bio_CMS_stream.pod
GENERATE[man/man3/PEM_write_bio_CMS_stream.3]=man3/PEM_write_bio_CMS_stream.pod
DEPEND[html/man3/PEM_write_bio_PKCS7_stream.html]=man3/PEM_write_bio_PKCS7_stream.pod
GENERATE[html/man3/PEM_write_bio_PKCS7_stream.html]=man3/PEM_write_bio_PKCS7_stream.pod
DEPEND[man/man3/PEM_write_bio_PKCS7_stream.3]=man3/PEM_write_bio_PKCS7_stream.pod
GENERATE[man/man3/PEM_write_bio_PKCS7_stream.3]=man3/PEM_write_bio_PKCS7_stream.pod
DEPEND[html/man3/PKCS12_PBE_keyivgen.html]=man3/PKCS12_PBE_keyivgen.pod
GENERATE[html/man3/PKCS12_PBE_keyivgen.html]=man3/PKCS12_PBE_keyivgen.pod
DEPEND[man/man3/PKCS12_PBE_keyivgen.3]=man3/PKCS12_PBE_keyivgen.pod
GENERATE[man/man3/PKCS12_PBE_keyivgen.3]=man3/PKCS12_PBE_keyivgen.pod
DEPEND[html/man3/PKCS12_SAFEBAG_create_cert.html]=man3/PKCS12_SAFEBAG_create_cert.pod
GENERATE[html/man3/PKCS12_SAFEBAG_create_cert.html]=man3/PKCS12_SAFEBAG_create_cert.pod
DEPEND[man/man3/PKCS12_SAFEBAG_create_cert.3]=man3/PKCS12_SAFEBAG_create_cert.pod
GENERATE[man/man3/PKCS12_SAFEBAG_create_cert.3]=man3/PKCS12_SAFEBAG_create_cert.pod
DEPEND[html/man3/PKCS12_SAFEBAG_get0_attrs.html]=man3/PKCS12_SAFEBAG_get0_attrs.pod
GENERATE[html/man3/PKCS12_SAFEBAG_get0_attrs.html]=man3/PKCS12_SAFEBAG_get0_attrs.pod
DEPEND[man/man3/PKCS12_SAFEBAG_get0_attrs.3]=man3/PKCS12_SAFEBAG_get0_attrs.pod
GENERATE[man/man3/PKCS12_SAFEBAG_get0_attrs.3]=man3/PKCS12_SAFEBAG_get0_attrs.pod
DEPEND[html/man3/PKCS12_SAFEBAG_get1_cert.html]=man3/PKCS12_SAFEBAG_get1_cert.pod
GENERATE[html/man3/PKCS12_SAFEBAG_get1_cert.html]=man3/PKCS12_SAFEBAG_get1_cert.pod
DEPEND[man/man3/PKCS12_SAFEBAG_get1_cert.3]=man3/PKCS12_SAFEBAG_get1_cert.pod
GENERATE[man/man3/PKCS12_SAFEBAG_get1_cert.3]=man3/PKCS12_SAFEBAG_get1_cert.pod
DEPEND[html/man3/PKCS12_add1_attr_by_NID.html]=man3/PKCS12_add1_attr_by_NID.pod
GENERATE[html/man3/PKCS12_add1_attr_by_NID.html]=man3/PKCS12_add1_attr_by_NID.pod
DEPEND[man/man3/PKCS12_add1_attr_by_NID.3]=man3/PKCS12_add1_attr_by_NID.pod
GENERATE[man/man3/PKCS12_add1_attr_by_NID.3]=man3/PKCS12_add1_attr_by_NID.pod
DEPEND[html/man3/PKCS12_add_CSPName_asc.html]=man3/PKCS12_add_CSPName_asc.pod
GENERATE[html/man3/PKCS12_add_CSPName_asc.html]=man3/PKCS12_add_CSPName_asc.pod
DEPEND[man/man3/PKCS12_add_CSPName_asc.3]=man3/PKCS12_add_CSPName_asc.pod
GENERATE[man/man3/PKCS12_add_CSPName_asc.3]=man3/PKCS12_add_CSPName_asc.pod
DEPEND[html/man3/PKCS12_add_cert.html]=man3/PKCS12_add_cert.pod
GENERATE[html/man3/PKCS12_add_cert.html]=man3/PKCS12_add_cert.pod
DEPEND[man/man3/PKCS12_add_cert.3]=man3/PKCS12_add_cert.pod
GENERATE[man/man3/PKCS12_add_cert.3]=man3/PKCS12_add_cert.pod
DEPEND[html/man3/PKCS12_add_friendlyname_asc.html]=man3/PKCS12_add_friendlyname_asc.pod
GENERATE[html/man3/PKCS12_add_friendlyname_asc.html]=man3/PKCS12_add_friendlyname_asc.pod
DEPEND[man/man3/PKCS12_add_friendlyname_asc.3]=man3/PKCS12_add_friendlyname_asc.pod
GENERATE[man/man3/PKCS12_add_friendlyname_asc.3]=man3/PKCS12_add_friendlyname_asc.pod
DEPEND[html/man3/PKCS12_add_localkeyid.html]=man3/PKCS12_add_localkeyid.pod
GENERATE[html/man3/PKCS12_add_localkeyid.html]=man3/PKCS12_add_localkeyid.pod
DEPEND[man/man3/PKCS12_add_localkeyid.3]=man3/PKCS12_add_localkeyid.pod
GENERATE[man/man3/PKCS12_add_localkeyid.3]=man3/PKCS12_add_localkeyid.pod
DEPEND[html/man3/PKCS12_add_safe.html]=man3/PKCS12_add_safe.pod
GENERATE[html/man3/PKCS12_add_safe.html]=man3/PKCS12_add_safe.pod
DEPEND[man/man3/PKCS12_add_safe.3]=man3/PKCS12_add_safe.pod
GENERATE[man/man3/PKCS12_add_safe.3]=man3/PKCS12_add_safe.pod
DEPEND[html/man3/PKCS12_create.html]=man3/PKCS12_create.pod
GENERATE[html/man3/PKCS12_create.html]=man3/PKCS12_create.pod
DEPEND[man/man3/PKCS12_create.3]=man3/PKCS12_create.pod
GENERATE[man/man3/PKCS12_create.3]=man3/PKCS12_create.pod
DEPEND[html/man3/PKCS12_decrypt_skey.html]=man3/PKCS12_decrypt_skey.pod
GENERATE[html/man3/PKCS12_decrypt_skey.html]=man3/PKCS12_decrypt_skey.pod
DEPEND[man/man3/PKCS12_decrypt_skey.3]=man3/PKCS12_decrypt_skey.pod
GENERATE[man/man3/PKCS12_decrypt_skey.3]=man3/PKCS12_decrypt_skey.pod
DEPEND[html/man3/PKCS12_gen_mac.html]=man3/PKCS12_gen_mac.pod
GENERATE[html/man3/PKCS12_gen_mac.html]=man3/PKCS12_gen_mac.pod
DEPEND[man/man3/PKCS12_gen_mac.3]=man3/PKCS12_gen_mac.pod
GENERATE[man/man3/PKCS12_gen_mac.3]=man3/PKCS12_gen_mac.pod
DEPEND[html/man3/PKCS12_get_friendlyname.html]=man3/PKCS12_get_friendlyname.pod
GENERATE[html/man3/PKCS12_get_friendlyname.html]=man3/PKCS12_get_friendlyname.pod
DEPEND[man/man3/PKCS12_get_friendlyname.3]=man3/PKCS12_get_friendlyname.pod
GENERATE[man/man3/PKCS12_get_friendlyname.3]=man3/PKCS12_get_friendlyname.pod
DEPEND[html/man3/PKCS12_init.html]=man3/PKCS12_init.pod
GENERATE[html/man3/PKCS12_init.html]=man3/PKCS12_init.pod
DEPEND[man/man3/PKCS12_init.3]=man3/PKCS12_init.pod
GENERATE[man/man3/PKCS12_init.3]=man3/PKCS12_init.pod
DEPEND[html/man3/PKCS12_item_decrypt_d2i.html]=man3/PKCS12_item_decrypt_d2i.pod
GENERATE[html/man3/PKCS12_item_decrypt_d2i.html]=man3/PKCS12_item_decrypt_d2i.pod
DEPEND[man/man3/PKCS12_item_decrypt_d2i.3]=man3/PKCS12_item_decrypt_d2i.pod
GENERATE[man/man3/PKCS12_item_decrypt_d2i.3]=man3/PKCS12_item_decrypt_d2i.pod
DEPEND[html/man3/PKCS12_key_gen_utf8_ex.html]=man3/PKCS12_key_gen_utf8_ex.pod
GENERATE[html/man3/PKCS12_key_gen_utf8_ex.html]=man3/PKCS12_key_gen_utf8_ex.pod
DEPEND[man/man3/PKCS12_key_gen_utf8_ex.3]=man3/PKCS12_key_gen_utf8_ex.pod
GENERATE[man/man3/PKCS12_key_gen_utf8_ex.3]=man3/PKCS12_key_gen_utf8_ex.pod
DEPEND[html/man3/PKCS12_newpass.html]=man3/PKCS12_newpass.pod
GENERATE[html/man3/PKCS12_newpass.html]=man3/PKCS12_newpass.pod
DEPEND[man/man3/PKCS12_newpass.3]=man3/PKCS12_newpass.pod
GENERATE[man/man3/PKCS12_newpass.3]=man3/PKCS12_newpass.pod
DEPEND[html/man3/PKCS12_pack_p7encdata.html]=man3/PKCS12_pack_p7encdata.pod
GENERATE[html/man3/PKCS12_pack_p7encdata.html]=man3/PKCS12_pack_p7encdata.pod
DEPEND[man/man3/PKCS12_pack_p7encdata.3]=man3/PKCS12_pack_p7encdata.pod
GENERATE[man/man3/PKCS12_pack_p7encdata.3]=man3/PKCS12_pack_p7encdata.pod
DEPEND[html/man3/PKCS12_parse.html]=man3/PKCS12_parse.pod
GENERATE[html/man3/PKCS12_parse.html]=man3/PKCS12_parse.pod
DEPEND[man/man3/PKCS12_parse.3]=man3/PKCS12_parse.pod
GENERATE[man/man3/PKCS12_parse.3]=man3/PKCS12_parse.pod
DEPEND[html/man3/PKCS5_PBE_keyivgen.html]=man3/PKCS5_PBE_keyivgen.pod
GENERATE[html/man3/PKCS5_PBE_keyivgen.html]=man3/PKCS5_PBE_keyivgen.pod
DEPEND[man/man3/PKCS5_PBE_keyivgen.3]=man3/PKCS5_PBE_keyivgen.pod
GENERATE[man/man3/PKCS5_PBE_keyivgen.3]=man3/PKCS5_PBE_keyivgen.pod
DEPEND[html/man3/PKCS5_PBKDF2_HMAC.html]=man3/PKCS5_PBKDF2_HMAC.pod
GENERATE[html/man3/PKCS5_PBKDF2_HMAC.html]=man3/PKCS5_PBKDF2_HMAC.pod
DEPEND[man/man3/PKCS5_PBKDF2_HMAC.3]=man3/PKCS5_PBKDF2_HMAC.pod
GENERATE[man/man3/PKCS5_PBKDF2_HMAC.3]=man3/PKCS5_PBKDF2_HMAC.pod
DEPEND[html/man3/PKCS7_decrypt.html]=man3/PKCS7_decrypt.pod
GENERATE[html/man3/PKCS7_decrypt.html]=man3/PKCS7_decrypt.pod
DEPEND[man/man3/PKCS7_decrypt.3]=man3/PKCS7_decrypt.pod
GENERATE[man/man3/PKCS7_decrypt.3]=man3/PKCS7_decrypt.pod
DEPEND[html/man3/PKCS7_encrypt.html]=man3/PKCS7_encrypt.pod
GENERATE[html/man3/PKCS7_encrypt.html]=man3/PKCS7_encrypt.pod
DEPEND[man/man3/PKCS7_encrypt.3]=man3/PKCS7_encrypt.pod
GENERATE[man/man3/PKCS7_encrypt.3]=man3/PKCS7_encrypt.pod
DEPEND[html/man3/PKCS7_get_octet_string.html]=man3/PKCS7_get_octet_string.pod
GENERATE[html/man3/PKCS7_get_octet_string.html]=man3/PKCS7_get_octet_string.pod
DEPEND[man/man3/PKCS7_get_octet_string.3]=man3/PKCS7_get_octet_string.pod
GENERATE[man/man3/PKCS7_get_octet_string.3]=man3/PKCS7_get_octet_string.pod
DEPEND[html/man3/PKCS7_sign.html]=man3/PKCS7_sign.pod
GENERATE[html/man3/PKCS7_sign.html]=man3/PKCS7_sign.pod
DEPEND[man/man3/PKCS7_sign.3]=man3/PKCS7_sign.pod
GENERATE[man/man3/PKCS7_sign.3]=man3/PKCS7_sign.pod
DEPEND[html/man3/PKCS7_sign_add_signer.html]=man3/PKCS7_sign_add_signer.pod
GENERATE[html/man3/PKCS7_sign_add_signer.html]=man3/PKCS7_sign_add_signer.pod
DEPEND[man/man3/PKCS7_sign_add_signer.3]=man3/PKCS7_sign_add_signer.pod
GENERATE[man/man3/PKCS7_sign_add_signer.3]=man3/PKCS7_sign_add_signer.pod
DEPEND[html/man3/PKCS7_type_is_other.html]=man3/PKCS7_type_is_other.pod
GENERATE[html/man3/PKCS7_type_is_other.html]=man3/PKCS7_type_is_other.pod
DEPEND[man/man3/PKCS7_type_is_other.3]=man3/PKCS7_type_is_other.pod
GENERATE[man/man3/PKCS7_type_is_other.3]=man3/PKCS7_type_is_other.pod
DEPEND[html/man3/PKCS7_verify.html]=man3/PKCS7_verify.pod
GENERATE[html/man3/PKCS7_verify.html]=man3/PKCS7_verify.pod
DEPEND[man/man3/PKCS7_verify.3]=man3/PKCS7_verify.pod
GENERATE[man/man3/PKCS7_verify.3]=man3/PKCS7_verify.pod
DEPEND[html/man3/PKCS8_encrypt.html]=man3/PKCS8_encrypt.pod
GENERATE[html/man3/PKCS8_encrypt.html]=man3/PKCS8_encrypt.pod
DEPEND[man/man3/PKCS8_encrypt.3]=man3/PKCS8_encrypt.pod
GENERATE[man/man3/PKCS8_encrypt.3]=man3/PKCS8_encrypt.pod
DEPEND[html/man3/PKCS8_pkey_add1_attr.html]=man3/PKCS8_pkey_add1_attr.pod
GENERATE[html/man3/PKCS8_pkey_add1_attr.html]=man3/PKCS8_pkey_add1_attr.pod
DEPEND[man/man3/PKCS8_pkey_add1_attr.3]=man3/PKCS8_pkey_add1_attr.pod
GENERATE[man/man3/PKCS8_pkey_add1_attr.3]=man3/PKCS8_pkey_add1_attr.pod
DEPEND[html/man3/RAND_add.html]=man3/RAND_add.pod
GENERATE[html/man3/RAND_add.html]=man3/RAND_add.pod
DEPEND[man/man3/RAND_add.3]=man3/RAND_add.pod
GENERATE[man/man3/RAND_add.3]=man3/RAND_add.pod
DEPEND[html/man3/RAND_bytes.html]=man3/RAND_bytes.pod
GENERATE[html/man3/RAND_bytes.html]=man3/RAND_bytes.pod
DEPEND[man/man3/RAND_bytes.3]=man3/RAND_bytes.pod
GENERATE[man/man3/RAND_bytes.3]=man3/RAND_bytes.pod
DEPEND[html/man3/RAND_cleanup.html]=man3/RAND_cleanup.pod
GENERATE[html/man3/RAND_cleanup.html]=man3/RAND_cleanup.pod
DEPEND[man/man3/RAND_cleanup.3]=man3/RAND_cleanup.pod
GENERATE[man/man3/RAND_cleanup.3]=man3/RAND_cleanup.pod
DEPEND[html/man3/RAND_egd.html]=man3/RAND_egd.pod
GENERATE[html/man3/RAND_egd.html]=man3/RAND_egd.pod
DEPEND[man/man3/RAND_egd.3]=man3/RAND_egd.pod
GENERATE[man/man3/RAND_egd.3]=man3/RAND_egd.pod
DEPEND[html/man3/RAND_get0_primary.html]=man3/RAND_get0_primary.pod
GENERATE[html/man3/RAND_get0_primary.html]=man3/RAND_get0_primary.pod
DEPEND[man/man3/RAND_get0_primary.3]=man3/RAND_get0_primary.pod
GENERATE[man/man3/RAND_get0_primary.3]=man3/RAND_get0_primary.pod
DEPEND[html/man3/RAND_load_file.html]=man3/RAND_load_file.pod
GENERATE[html/man3/RAND_load_file.html]=man3/RAND_load_file.pod
DEPEND[man/man3/RAND_load_file.3]=man3/RAND_load_file.pod
GENERATE[man/man3/RAND_load_file.3]=man3/RAND_load_file.pod
DEPEND[html/man3/RAND_set_DRBG_type.html]=man3/RAND_set_DRBG_type.pod
GENERATE[html/man3/RAND_set_DRBG_type.html]=man3/RAND_set_DRBG_type.pod
DEPEND[man/man3/RAND_set_DRBG_type.3]=man3/RAND_set_DRBG_type.pod
GENERATE[man/man3/RAND_set_DRBG_type.3]=man3/RAND_set_DRBG_type.pod
DEPEND[html/man3/RAND_set_rand_method.html]=man3/RAND_set_rand_method.pod
GENERATE[html/man3/RAND_set_rand_method.html]=man3/RAND_set_rand_method.pod
DEPEND[man/man3/RAND_set_rand_method.3]=man3/RAND_set_rand_method.pod
GENERATE[man/man3/RAND_set_rand_method.3]=man3/RAND_set_rand_method.pod
DEPEND[html/man3/RC4_set_key.html]=man3/RC4_set_key.pod
GENERATE[html/man3/RC4_set_key.html]=man3/RC4_set_key.pod
DEPEND[man/man3/RC4_set_key.3]=man3/RC4_set_key.pod
GENERATE[man/man3/RC4_set_key.3]=man3/RC4_set_key.pod
DEPEND[html/man3/RIPEMD160_Init.html]=man3/RIPEMD160_Init.pod
GENERATE[html/man3/RIPEMD160_Init.html]=man3/RIPEMD160_Init.pod
DEPEND[man/man3/RIPEMD160_Init.3]=man3/RIPEMD160_Init.pod
GENERATE[man/man3/RIPEMD160_Init.3]=man3/RIPEMD160_Init.pod
DEPEND[html/man3/RSA_blinding_on.html]=man3/RSA_blinding_on.pod
GENERATE[html/man3/RSA_blinding_on.html]=man3/RSA_blinding_on.pod
DEPEND[man/man3/RSA_blinding_on.3]=man3/RSA_blinding_on.pod
GENERATE[man/man3/RSA_blinding_on.3]=man3/RSA_blinding_on.pod
DEPEND[html/man3/RSA_check_key.html]=man3/RSA_check_key.pod
GENERATE[html/man3/RSA_check_key.html]=man3/RSA_check_key.pod
DEPEND[man/man3/RSA_check_key.3]=man3/RSA_check_key.pod
GENERATE[man/man3/RSA_check_key.3]=man3/RSA_check_key.pod
DEPEND[html/man3/RSA_generate_key.html]=man3/RSA_generate_key.pod
GENERATE[html/man3/RSA_generate_key.html]=man3/RSA_generate_key.pod
DEPEND[man/man3/RSA_generate_key.3]=man3/RSA_generate_key.pod
GENERATE[man/man3/RSA_generate_key.3]=man3/RSA_generate_key.pod
DEPEND[html/man3/RSA_get0_key.html]=man3/RSA_get0_key.pod
GENERATE[html/man3/RSA_get0_key.html]=man3/RSA_get0_key.pod
DEPEND[man/man3/RSA_get0_key.3]=man3/RSA_get0_key.pod
GENERATE[man/man3/RSA_get0_key.3]=man3/RSA_get0_key.pod
DEPEND[html/man3/RSA_meth_new.html]=man3/RSA_meth_new.pod
GENERATE[html/man3/RSA_meth_new.html]=man3/RSA_meth_new.pod
DEPEND[man/man3/RSA_meth_new.3]=man3/RSA_meth_new.pod
GENERATE[man/man3/RSA_meth_new.3]=man3/RSA_meth_new.pod
DEPEND[html/man3/RSA_new.html]=man3/RSA_new.pod
GENERATE[html/man3/RSA_new.html]=man3/RSA_new.pod
DEPEND[man/man3/RSA_new.3]=man3/RSA_new.pod
GENERATE[man/man3/RSA_new.3]=man3/RSA_new.pod
DEPEND[html/man3/RSA_padding_add_PKCS1_type_1.html]=man3/RSA_padding_add_PKCS1_type_1.pod
GENERATE[html/man3/RSA_padding_add_PKCS1_type_1.html]=man3/RSA_padding_add_PKCS1_type_1.pod
DEPEND[man/man3/RSA_padding_add_PKCS1_type_1.3]=man3/RSA_padding_add_PKCS1_type_1.pod
GENERATE[man/man3/RSA_padding_add_PKCS1_type_1.3]=man3/RSA_padding_add_PKCS1_type_1.pod
DEPEND[html/man3/RSA_print.html]=man3/RSA_print.pod
GENERATE[html/man3/RSA_print.html]=man3/RSA_print.pod
DEPEND[man/man3/RSA_print.3]=man3/RSA_print.pod
GENERATE[man/man3/RSA_print.3]=man3/RSA_print.pod
DEPEND[html/man3/RSA_private_encrypt.html]=man3/RSA_private_encrypt.pod
GENERATE[html/man3/RSA_private_encrypt.html]=man3/RSA_private_encrypt.pod
DEPEND[man/man3/RSA_private_encrypt.3]=man3/RSA_private_encrypt.pod
GENERATE[man/man3/RSA_private_encrypt.3]=man3/RSA_private_encrypt.pod
DEPEND[html/man3/RSA_public_encrypt.html]=man3/RSA_public_encrypt.pod
GENERATE[html/man3/RSA_public_encrypt.html]=man3/RSA_public_encrypt.pod
DEPEND[man/man3/RSA_public_encrypt.3]=man3/RSA_public_encrypt.pod
GENERATE[man/man3/RSA_public_encrypt.3]=man3/RSA_public_encrypt.pod
DEPEND[html/man3/RSA_set_method.html]=man3/RSA_set_method.pod
GENERATE[html/man3/RSA_set_method.html]=man3/RSA_set_method.pod
DEPEND[man/man3/RSA_set_method.3]=man3/RSA_set_method.pod
GENERATE[man/man3/RSA_set_method.3]=man3/RSA_set_method.pod
DEPEND[html/man3/RSA_sign.html]=man3/RSA_sign.pod
GENERATE[html/man3/RSA_sign.html]=man3/RSA_sign.pod
DEPEND[man/man3/RSA_sign.3]=man3/RSA_sign.pod
GENERATE[man/man3/RSA_sign.3]=man3/RSA_sign.pod
DEPEND[html/man3/RSA_sign_ASN1_OCTET_STRING.html]=man3/RSA_sign_ASN1_OCTET_STRING.pod
GENERATE[html/man3/RSA_sign_ASN1_OCTET_STRING.html]=man3/RSA_sign_ASN1_OCTET_STRING.pod
DEPEND[man/man3/RSA_sign_ASN1_OCTET_STRING.3]=man3/RSA_sign_ASN1_OCTET_STRING.pod
GENERATE[man/man3/RSA_sign_ASN1_OCTET_STRING.3]=man3/RSA_sign_ASN1_OCTET_STRING.pod
DEPEND[html/man3/RSA_size.html]=man3/RSA_size.pod
GENERATE[html/man3/RSA_size.html]=man3/RSA_size.pod
DEPEND[man/man3/RSA_size.3]=man3/RSA_size.pod
GENERATE[man/man3/RSA_size.3]=man3/RSA_size.pod
DEPEND[html/man3/SCT_new.html]=man3/SCT_new.pod
GENERATE[html/man3/SCT_new.html]=man3/SCT_new.pod
DEPEND[man/man3/SCT_new.3]=man3/SCT_new.pod
GENERATE[man/man3/SCT_new.3]=man3/SCT_new.pod
DEPEND[html/man3/SCT_print.html]=man3/SCT_print.pod
GENERATE[html/man3/SCT_print.html]=man3/SCT_print.pod
DEPEND[man/man3/SCT_print.3]=man3/SCT_print.pod
GENERATE[man/man3/SCT_print.3]=man3/SCT_print.pod
DEPEND[html/man3/SCT_validate.html]=man3/SCT_validate.pod
GENERATE[html/man3/SCT_validate.html]=man3/SCT_validate.pod
DEPEND[man/man3/SCT_validate.3]=man3/SCT_validate.pod
GENERATE[man/man3/SCT_validate.3]=man3/SCT_validate.pod
DEPEND[html/man3/SHA256_Init.html]=man3/SHA256_Init.pod
GENERATE[html/man3/SHA256_Init.html]=man3/SHA256_Init.pod
DEPEND[man/man3/SHA256_Init.3]=man3/SHA256_Init.pod
GENERATE[man/man3/SHA256_Init.3]=man3/SHA256_Init.pod
DEPEND[html/man3/SMIME_read_ASN1.html]=man3/SMIME_read_ASN1.pod
GENERATE[html/man3/SMIME_read_ASN1.html]=man3/SMIME_read_ASN1.pod
DEPEND[man/man3/SMIME_read_ASN1.3]=man3/SMIME_read_ASN1.pod
GENERATE[man/man3/SMIME_read_ASN1.3]=man3/SMIME_read_ASN1.pod
DEPEND[html/man3/SMIME_read_CMS.html]=man3/SMIME_read_CMS.pod
GENERATE[html/man3/SMIME_read_CMS.html]=man3/SMIME_read_CMS.pod
DEPEND[man/man3/SMIME_read_CMS.3]=man3/SMIME_read_CMS.pod
GENERATE[man/man3/SMIME_read_CMS.3]=man3/SMIME_read_CMS.pod
DEPEND[html/man3/SMIME_read_PKCS7.html]=man3/SMIME_read_PKCS7.pod
GENERATE[html/man3/SMIME_read_PKCS7.html]=man3/SMIME_read_PKCS7.pod
DEPEND[man/man3/SMIME_read_PKCS7.3]=man3/SMIME_read_PKCS7.pod
GENERATE[man/man3/SMIME_read_PKCS7.3]=man3/SMIME_read_PKCS7.pod
DEPEND[html/man3/SMIME_write_ASN1.html]=man3/SMIME_write_ASN1.pod
GENERATE[html/man3/SMIME_write_ASN1.html]=man3/SMIME_write_ASN1.pod
DEPEND[man/man3/SMIME_write_ASN1.3]=man3/SMIME_write_ASN1.pod
GENERATE[man/man3/SMIME_write_ASN1.3]=man3/SMIME_write_ASN1.pod
DEPEND[html/man3/SMIME_write_CMS.html]=man3/SMIME_write_CMS.pod
GENERATE[html/man3/SMIME_write_CMS.html]=man3/SMIME_write_CMS.pod
DEPEND[man/man3/SMIME_write_CMS.3]=man3/SMIME_write_CMS.pod
GENERATE[man/man3/SMIME_write_CMS.3]=man3/SMIME_write_CMS.pod
DEPEND[html/man3/SMIME_write_PKCS7.html]=man3/SMIME_write_PKCS7.pod
GENERATE[html/man3/SMIME_write_PKCS7.html]=man3/SMIME_write_PKCS7.pod
DEPEND[man/man3/SMIME_write_PKCS7.3]=man3/SMIME_write_PKCS7.pod
GENERATE[man/man3/SMIME_write_PKCS7.3]=man3/SMIME_write_PKCS7.pod
DEPEND[html/man3/SRP_Calc_B.html]=man3/SRP_Calc_B.pod
GENERATE[html/man3/SRP_Calc_B.html]=man3/SRP_Calc_B.pod
DEPEND[man/man3/SRP_Calc_B.3]=man3/SRP_Calc_B.pod
GENERATE[man/man3/SRP_Calc_B.3]=man3/SRP_Calc_B.pod
DEPEND[html/man3/SRP_VBASE_new.html]=man3/SRP_VBASE_new.pod
GENERATE[html/man3/SRP_VBASE_new.html]=man3/SRP_VBASE_new.pod
DEPEND[man/man3/SRP_VBASE_new.3]=man3/SRP_VBASE_new.pod
GENERATE[man/man3/SRP_VBASE_new.3]=man3/SRP_VBASE_new.pod
DEPEND[html/man3/SRP_create_verifier.html]=man3/SRP_create_verifier.pod
GENERATE[html/man3/SRP_create_verifier.html]=man3/SRP_create_verifier.pod
DEPEND[man/man3/SRP_create_verifier.3]=man3/SRP_create_verifier.pod
GENERATE[man/man3/SRP_create_verifier.3]=man3/SRP_create_verifier.pod
DEPEND[html/man3/SRP_user_pwd_new.html]=man3/SRP_user_pwd_new.pod
GENERATE[html/man3/SRP_user_pwd_new.html]=man3/SRP_user_pwd_new.pod
DEPEND[man/man3/SRP_user_pwd_new.3]=man3/SRP_user_pwd_new.pod
GENERATE[man/man3/SRP_user_pwd_new.3]=man3/SRP_user_pwd_new.pod
DEPEND[html/man3/SSL_CIPHER_get_name.html]=man3/SSL_CIPHER_get_name.pod
GENERATE[html/man3/SSL_CIPHER_get_name.html]=man3/SSL_CIPHER_get_name.pod
DEPEND[man/man3/SSL_CIPHER_get_name.3]=man3/SSL_CIPHER_get_name.pod
GENERATE[man/man3/SSL_CIPHER_get_name.3]=man3/SSL_CIPHER_get_name.pod
DEPEND[html/man3/SSL_COMP_add_compression_method.html]=man3/SSL_COMP_add_compression_method.pod
GENERATE[html/man3/SSL_COMP_add_compression_method.html]=man3/SSL_COMP_add_compression_method.pod
DEPEND[man/man3/SSL_COMP_add_compression_method.3]=man3/SSL_COMP_add_compression_method.pod
GENERATE[man/man3/SSL_COMP_add_compression_method.3]=man3/SSL_COMP_add_compression_method.pod
DEPEND[html/man3/SSL_CONF_CTX_new.html]=man3/SSL_CONF_CTX_new.pod
GENERATE[html/man3/SSL_CONF_CTX_new.html]=man3/SSL_CONF_CTX_new.pod
DEPEND[man/man3/SSL_CONF_CTX_new.3]=man3/SSL_CONF_CTX_new.pod
GENERATE[man/man3/SSL_CONF_CTX_new.3]=man3/SSL_CONF_CTX_new.pod
DEPEND[html/man3/SSL_CONF_CTX_set1_prefix.html]=man3/SSL_CONF_CTX_set1_prefix.pod
GENERATE[html/man3/SSL_CONF_CTX_set1_prefix.html]=man3/SSL_CONF_CTX_set1_prefix.pod
DEPEND[man/man3/SSL_CONF_CTX_set1_prefix.3]=man3/SSL_CONF_CTX_set1_prefix.pod
GENERATE[man/man3/SSL_CONF_CTX_set1_prefix.3]=man3/SSL_CONF_CTX_set1_prefix.pod
DEPEND[html/man3/SSL_CONF_CTX_set_flags.html]=man3/SSL_CONF_CTX_set_flags.pod
GENERATE[html/man3/SSL_CONF_CTX_set_flags.html]=man3/SSL_CONF_CTX_set_flags.pod
DEPEND[man/man3/SSL_CONF_CTX_set_flags.3]=man3/SSL_CONF_CTX_set_flags.pod
GENERATE[man/man3/SSL_CONF_CTX_set_flags.3]=man3/SSL_CONF_CTX_set_flags.pod
DEPEND[html/man3/SSL_CONF_CTX_set_ssl_ctx.html]=man3/SSL_CONF_CTX_set_ssl_ctx.pod
GENERATE[html/man3/SSL_CONF_CTX_set_ssl_ctx.html]=man3/SSL_CONF_CTX_set_ssl_ctx.pod
DEPEND[man/man3/SSL_CONF_CTX_set_ssl_ctx.3]=man3/SSL_CONF_CTX_set_ssl_ctx.pod
GENERATE[man/man3/SSL_CONF_CTX_set_ssl_ctx.3]=man3/SSL_CONF_CTX_set_ssl_ctx.pod
DEPEND[html/man3/SSL_CONF_cmd.html]=man3/SSL_CONF_cmd.pod
GENERATE[html/man3/SSL_CONF_cmd.html]=man3/SSL_CONF_cmd.pod
DEPEND[man/man3/SSL_CONF_cmd.3]=man3/SSL_CONF_cmd.pod
GENERATE[man/man3/SSL_CONF_cmd.3]=man3/SSL_CONF_cmd.pod
DEPEND[html/man3/SSL_CONF_cmd_argv.html]=man3/SSL_CONF_cmd_argv.pod
GENERATE[html/man3/SSL_CONF_cmd_argv.html]=man3/SSL_CONF_cmd_argv.pod
DEPEND[man/man3/SSL_CONF_cmd_argv.3]=man3/SSL_CONF_cmd_argv.pod
GENERATE[man/man3/SSL_CONF_cmd_argv.3]=man3/SSL_CONF_cmd_argv.pod
DEPEND[html/man3/SSL_CTX_add1_chain_cert.html]=man3/SSL_CTX_add1_chain_cert.pod
GENERATE[html/man3/SSL_CTX_add1_chain_cert.html]=man3/SSL_CTX_add1_chain_cert.pod
DEPEND[man/man3/SSL_CTX_add1_chain_cert.3]=man3/SSL_CTX_add1_chain_cert.pod
GENERATE[man/man3/SSL_CTX_add1_chain_cert.3]=man3/SSL_CTX_add1_chain_cert.pod
DEPEND[html/man3/SSL_CTX_add_extra_chain_cert.html]=man3/SSL_CTX_add_extra_chain_cert.pod
GENERATE[html/man3/SSL_CTX_add_extra_chain_cert.html]=man3/SSL_CTX_add_extra_chain_cert.pod
DEPEND[man/man3/SSL_CTX_add_extra_chain_cert.3]=man3/SSL_CTX_add_extra_chain_cert.pod
GENERATE[man/man3/SSL_CTX_add_extra_chain_cert.3]=man3/SSL_CTX_add_extra_chain_cert.pod
DEPEND[html/man3/SSL_CTX_add_session.html]=man3/SSL_CTX_add_session.pod
GENERATE[html/man3/SSL_CTX_add_session.html]=man3/SSL_CTX_add_session.pod
DEPEND[man/man3/SSL_CTX_add_session.3]=man3/SSL_CTX_add_session.pod
GENERATE[man/man3/SSL_CTX_add_session.3]=man3/SSL_CTX_add_session.pod
DEPEND[html/man3/SSL_CTX_config.html]=man3/SSL_CTX_config.pod
GENERATE[html/man3/SSL_CTX_config.html]=man3/SSL_CTX_config.pod
DEPEND[man/man3/SSL_CTX_config.3]=man3/SSL_CTX_config.pod
GENERATE[man/man3/SSL_CTX_config.3]=man3/SSL_CTX_config.pod
DEPEND[html/man3/SSL_CTX_ctrl.html]=man3/SSL_CTX_ctrl.pod
GENERATE[html/man3/SSL_CTX_ctrl.html]=man3/SSL_CTX_ctrl.pod
DEPEND[man/man3/SSL_CTX_ctrl.3]=man3/SSL_CTX_ctrl.pod
GENERATE[man/man3/SSL_CTX_ctrl.3]=man3/SSL_CTX_ctrl.pod
DEPEND[html/man3/SSL_CTX_dane_enable.html]=man3/SSL_CTX_dane_enable.pod
GENERATE[html/man3/SSL_CTX_dane_enable.html]=man3/SSL_CTX_dane_enable.pod
DEPEND[man/man3/SSL_CTX_dane_enable.3]=man3/SSL_CTX_dane_enable.pod
GENERATE[man/man3/SSL_CTX_dane_enable.3]=man3/SSL_CTX_dane_enable.pod
DEPEND[html/man3/SSL_CTX_flush_sessions.html]=man3/SSL_CTX_flush_sessions.pod
GENERATE[html/man3/SSL_CTX_flush_sessions.html]=man3/SSL_CTX_flush_sessions.pod
DEPEND[man/man3/SSL_CTX_flush_sessions.3]=man3/SSL_CTX_flush_sessions.pod
GENERATE[man/man3/SSL_CTX_flush_sessions.3]=man3/SSL_CTX_flush_sessions.pod
DEPEND[html/man3/SSL_CTX_free.html]=man3/SSL_CTX_free.pod
GENERATE[html/man3/SSL_CTX_free.html]=man3/SSL_CTX_free.pod
DEPEND[man/man3/SSL_CTX_free.3]=man3/SSL_CTX_free.pod
GENERATE[man/man3/SSL_CTX_free.3]=man3/SSL_CTX_free.pod
DEPEND[html/man3/SSL_CTX_get0_param.html]=man3/SSL_CTX_get0_param.pod
GENERATE[html/man3/SSL_CTX_get0_param.html]=man3/SSL_CTX_get0_param.pod
DEPEND[man/man3/SSL_CTX_get0_param.3]=man3/SSL_CTX_get0_param.pod
GENERATE[man/man3/SSL_CTX_get0_param.3]=man3/SSL_CTX_get0_param.pod
DEPEND[html/man3/SSL_CTX_get_verify_mode.html]=man3/SSL_CTX_get_verify_mode.pod
GENERATE[html/man3/SSL_CTX_get_verify_mode.html]=man3/SSL_CTX_get_verify_mode.pod
DEPEND[man/man3/SSL_CTX_get_verify_mode.3]=man3/SSL_CTX_get_verify_mode.pod
GENERATE[man/man3/SSL_CTX_get_verify_mode.3]=man3/SSL_CTX_get_verify_mode.pod
DEPEND[html/man3/SSL_CTX_has_client_custom_ext.html]=man3/SSL_CTX_has_client_custom_ext.pod
GENERATE[html/man3/SSL_CTX_has_client_custom_ext.html]=man3/SSL_CTX_has_client_custom_ext.pod
DEPEND[man/man3/SSL_CTX_has_client_custom_ext.3]=man3/SSL_CTX_has_client_custom_ext.pod
GENERATE[man/man3/SSL_CTX_has_client_custom_ext.3]=man3/SSL_CTX_has_client_custom_ext.pod
DEPEND[html/man3/SSL_CTX_load_verify_locations.html]=man3/SSL_CTX_load_verify_locations.pod
GENERATE[html/man3/SSL_CTX_load_verify_locations.html]=man3/SSL_CTX_load_verify_locations.pod
DEPEND[man/man3/SSL_CTX_load_verify_locations.3]=man3/SSL_CTX_load_verify_locations.pod
GENERATE[man/man3/SSL_CTX_load_verify_locations.3]=man3/SSL_CTX_load_verify_locations.pod
DEPEND[html/man3/SSL_CTX_new.html]=man3/SSL_CTX_new.pod
GENERATE[html/man3/SSL_CTX_new.html]=man3/SSL_CTX_new.pod
DEPEND[man/man3/SSL_CTX_new.3]=man3/SSL_CTX_new.pod
GENERATE[man/man3/SSL_CTX_new.3]=man3/SSL_CTX_new.pod
DEPEND[html/man3/SSL_CTX_sess_number.html]=man3/SSL_CTX_sess_number.pod
GENERATE[html/man3/SSL_CTX_sess_number.html]=man3/SSL_CTX_sess_number.pod
DEPEND[man/man3/SSL_CTX_sess_number.3]=man3/SSL_CTX_sess_number.pod
GENERATE[man/man3/SSL_CTX_sess_number.3]=man3/SSL_CTX_sess_number.pod
DEPEND[html/man3/SSL_CTX_sess_set_cache_size.html]=man3/SSL_CTX_sess_set_cache_size.pod
GENERATE[html/man3/SSL_CTX_sess_set_cache_size.html]=man3/SSL_CTX_sess_set_cache_size.pod
DEPEND[man/man3/SSL_CTX_sess_set_cache_size.3]=man3/SSL_CTX_sess_set_cache_size.pod
GENERATE[man/man3/SSL_CTX_sess_set_cache_size.3]=man3/SSL_CTX_sess_set_cache_size.pod
DEPEND[html/man3/SSL_CTX_sess_set_get_cb.html]=man3/SSL_CTX_sess_set_get_cb.pod
GENERATE[html/man3/SSL_CTX_sess_set_get_cb.html]=man3/SSL_CTX_sess_set_get_cb.pod
DEPEND[man/man3/SSL_CTX_sess_set_get_cb.3]=man3/SSL_CTX_sess_set_get_cb.pod
GENERATE[man/man3/SSL_CTX_sess_set_get_cb.3]=man3/SSL_CTX_sess_set_get_cb.pod
DEPEND[html/man3/SSL_CTX_sessions.html]=man3/SSL_CTX_sessions.pod
GENERATE[html/man3/SSL_CTX_sessions.html]=man3/SSL_CTX_sessions.pod
DEPEND[man/man3/SSL_CTX_sessions.3]=man3/SSL_CTX_sessions.pod
GENERATE[man/man3/SSL_CTX_sessions.3]=man3/SSL_CTX_sessions.pod
DEPEND[html/man3/SSL_CTX_set0_CA_list.html]=man3/SSL_CTX_set0_CA_list.pod
GENERATE[html/man3/SSL_CTX_set0_CA_list.html]=man3/SSL_CTX_set0_CA_list.pod
DEPEND[man/man3/SSL_CTX_set0_CA_list.3]=man3/SSL_CTX_set0_CA_list.pod
GENERATE[man/man3/SSL_CTX_set0_CA_list.3]=man3/SSL_CTX_set0_CA_list.pod
DEPEND[html/man3/SSL_CTX_set1_curves.html]=man3/SSL_CTX_set1_curves.pod
GENERATE[html/man3/SSL_CTX_set1_curves.html]=man3/SSL_CTX_set1_curves.pod
DEPEND[man/man3/SSL_CTX_set1_curves.3]=man3/SSL_CTX_set1_curves.pod
GENERATE[man/man3/SSL_CTX_set1_curves.3]=man3/SSL_CTX_set1_curves.pod
DEPEND[html/man3/SSL_CTX_set1_sigalgs.html]=man3/SSL_CTX_set1_sigalgs.pod
GENERATE[html/man3/SSL_CTX_set1_sigalgs.html]=man3/SSL_CTX_set1_sigalgs.pod
DEPEND[man/man3/SSL_CTX_set1_sigalgs.3]=man3/SSL_CTX_set1_sigalgs.pod
GENERATE[man/man3/SSL_CTX_set1_sigalgs.3]=man3/SSL_CTX_set1_sigalgs.pod
DEPEND[html/man3/SSL_CTX_set1_verify_cert_store.html]=man3/SSL_CTX_set1_verify_cert_store.pod
GENERATE[html/man3/SSL_CTX_set1_verify_cert_store.html]=man3/SSL_CTX_set1_verify_cert_store.pod
DEPEND[man/man3/SSL_CTX_set1_verify_cert_store.3]=man3/SSL_CTX_set1_verify_cert_store.pod
GENERATE[man/man3/SSL_CTX_set1_verify_cert_store.3]=man3/SSL_CTX_set1_verify_cert_store.pod
DEPEND[html/man3/SSL_CTX_set_alpn_select_cb.html]=man3/SSL_CTX_set_alpn_select_cb.pod
GENERATE[html/man3/SSL_CTX_set_alpn_select_cb.html]=man3/SSL_CTX_set_alpn_select_cb.pod
DEPEND[man/man3/SSL_CTX_set_alpn_select_cb.3]=man3/SSL_CTX_set_alpn_select_cb.pod
GENERATE[man/man3/SSL_CTX_set_alpn_select_cb.3]=man3/SSL_CTX_set_alpn_select_cb.pod
DEPEND[html/man3/SSL_CTX_set_cert_cb.html]=man3/SSL_CTX_set_cert_cb.pod
GENERATE[html/man3/SSL_CTX_set_cert_cb.html]=man3/SSL_CTX_set_cert_cb.pod
DEPEND[man/man3/SSL_CTX_set_cert_cb.3]=man3/SSL_CTX_set_cert_cb.pod
GENERATE[man/man3/SSL_CTX_set_cert_cb.3]=man3/SSL_CTX_set_cert_cb.pod
DEPEND[html/man3/SSL_CTX_set_cert_store.html]=man3/SSL_CTX_set_cert_store.pod
GENERATE[html/man3/SSL_CTX_set_cert_store.html]=man3/SSL_CTX_set_cert_store.pod
DEPEND[man/man3/SSL_CTX_set_cert_store.3]=man3/SSL_CTX_set_cert_store.pod
GENERATE[man/man3/SSL_CTX_set_cert_store.3]=man3/SSL_CTX_set_cert_store.pod
DEPEND[html/man3/SSL_CTX_set_cert_verify_callback.html]=man3/SSL_CTX_set_cert_verify_callback.pod
GENERATE[html/man3/SSL_CTX_set_cert_verify_callback.html]=man3/SSL_CTX_set_cert_verify_callback.pod
DEPEND[man/man3/SSL_CTX_set_cert_verify_callback.3]=man3/SSL_CTX_set_cert_verify_callback.pod
GENERATE[man/man3/SSL_CTX_set_cert_verify_callback.3]=man3/SSL_CTX_set_cert_verify_callback.pod
DEPEND[html/man3/SSL_CTX_set_cipher_list.html]=man3/SSL_CTX_set_cipher_list.pod
GENERATE[html/man3/SSL_CTX_set_cipher_list.html]=man3/SSL_CTX_set_cipher_list.pod
DEPEND[man/man3/SSL_CTX_set_cipher_list.3]=man3/SSL_CTX_set_cipher_list.pod
GENERATE[man/man3/SSL_CTX_set_cipher_list.3]=man3/SSL_CTX_set_cipher_list.pod
DEPEND[html/man3/SSL_CTX_set_client_cert_cb.html]=man3/SSL_CTX_set_client_cert_cb.pod
GENERATE[html/man3/SSL_CTX_set_client_cert_cb.html]=man3/SSL_CTX_set_client_cert_cb.pod
DEPEND[man/man3/SSL_CTX_set_client_cert_cb.3]=man3/SSL_CTX_set_client_cert_cb.pod
GENERATE[man/man3/SSL_CTX_set_client_cert_cb.3]=man3/SSL_CTX_set_client_cert_cb.pod
DEPEND[html/man3/SSL_CTX_set_client_hello_cb.html]=man3/SSL_CTX_set_client_hello_cb.pod
GENERATE[html/man3/SSL_CTX_set_client_hello_cb.html]=man3/SSL_CTX_set_client_hello_cb.pod
DEPEND[man/man3/SSL_CTX_set_client_hello_cb.3]=man3/SSL_CTX_set_client_hello_cb.pod
GENERATE[man/man3/SSL_CTX_set_client_hello_cb.3]=man3/SSL_CTX_set_client_hello_cb.pod
DEPEND[html/man3/SSL_CTX_set_ct_validation_callback.html]=man3/SSL_CTX_set_ct_validation_callback.pod
GENERATE[html/man3/SSL_CTX_set_ct_validation_callback.html]=man3/SSL_CTX_set_ct_validation_callback.pod
DEPEND[man/man3/SSL_CTX_set_ct_validation_callback.3]=man3/SSL_CTX_set_ct_validation_callback.pod
GENERATE[man/man3/SSL_CTX_set_ct_validation_callback.3]=man3/SSL_CTX_set_ct_validation_callback.pod
DEPEND[html/man3/SSL_CTX_set_ctlog_list_file.html]=man3/SSL_CTX_set_ctlog_list_file.pod
GENERATE[html/man3/SSL_CTX_set_ctlog_list_file.html]=man3/SSL_CTX_set_ctlog_list_file.pod
DEPEND[man/man3/SSL_CTX_set_ctlog_list_file.3]=man3/SSL_CTX_set_ctlog_list_file.pod
GENERATE[man/man3/SSL_CTX_set_ctlog_list_file.3]=man3/SSL_CTX_set_ctlog_list_file.pod
DEPEND[html/man3/SSL_CTX_set_default_passwd_cb.html]=man3/SSL_CTX_set_default_passwd_cb.pod
GENERATE[html/man3/SSL_CTX_set_default_passwd_cb.html]=man3/SSL_CTX_set_default_passwd_cb.pod
DEPEND[man/man3/SSL_CTX_set_default_passwd_cb.3]=man3/SSL_CTX_set_default_passwd_cb.pod
GENERATE[man/man3/SSL_CTX_set_default_passwd_cb.3]=man3/SSL_CTX_set_default_passwd_cb.pod
DEPEND[html/man3/SSL_CTX_set_generate_session_id.html]=man3/SSL_CTX_set_generate_session_id.pod
GENERATE[html/man3/SSL_CTX_set_generate_session_id.html]=man3/SSL_CTX_set_generate_session_id.pod
DEPEND[man/man3/SSL_CTX_set_generate_session_id.3]=man3/SSL_CTX_set_generate_session_id.pod
GENERATE[man/man3/SSL_CTX_set_generate_session_id.3]=man3/SSL_CTX_set_generate_session_id.pod
DEPEND[html/man3/SSL_CTX_set_info_callback.html]=man3/SSL_CTX_set_info_callback.pod
GENERATE[html/man3/SSL_CTX_set_info_callback.html]=man3/SSL_CTX_set_info_callback.pod
DEPEND[man/man3/SSL_CTX_set_info_callback.3]=man3/SSL_CTX_set_info_callback.pod
GENERATE[man/man3/SSL_CTX_set_info_callback.3]=man3/SSL_CTX_set_info_callback.pod
DEPEND[html/man3/SSL_CTX_set_keylog_callback.html]=man3/SSL_CTX_set_keylog_callback.pod
GENERATE[html/man3/SSL_CTX_set_keylog_callback.html]=man3/SSL_CTX_set_keylog_callback.pod
DEPEND[man/man3/SSL_CTX_set_keylog_callback.3]=man3/SSL_CTX_set_keylog_callback.pod
GENERATE[man/man3/SSL_CTX_set_keylog_callback.3]=man3/SSL_CTX_set_keylog_callback.pod
DEPEND[html/man3/SSL_CTX_set_max_cert_list.html]=man3/SSL_CTX_set_max_cert_list.pod
GENERATE[html/man3/SSL_CTX_set_max_cert_list.html]=man3/SSL_CTX_set_max_cert_list.pod
DEPEND[man/man3/SSL_CTX_set_max_cert_list.3]=man3/SSL_CTX_set_max_cert_list.pod
GENERATE[man/man3/SSL_CTX_set_max_cert_list.3]=man3/SSL_CTX_set_max_cert_list.pod
DEPEND[html/man3/SSL_CTX_set_min_proto_version.html]=man3/SSL_CTX_set_min_proto_version.pod
GENERATE[html/man3/SSL_CTX_set_min_proto_version.html]=man3/SSL_CTX_set_min_proto_version.pod
DEPEND[man/man3/SSL_CTX_set_min_proto_version.3]=man3/SSL_CTX_set_min_proto_version.pod
GENERATE[man/man3/SSL_CTX_set_min_proto_version.3]=man3/SSL_CTX_set_min_proto_version.pod
DEPEND[html/man3/SSL_CTX_set_mode.html]=man3/SSL_CTX_set_mode.pod
GENERATE[html/man3/SSL_CTX_set_mode.html]=man3/SSL_CTX_set_mode.pod
DEPEND[man/man3/SSL_CTX_set_mode.3]=man3/SSL_CTX_set_mode.pod
GENERATE[man/man3/SSL_CTX_set_mode.3]=man3/SSL_CTX_set_mode.pod
DEPEND[html/man3/SSL_CTX_set_msg_callback.html]=man3/SSL_CTX_set_msg_callback.pod
GENERATE[html/man3/SSL_CTX_set_msg_callback.html]=man3/SSL_CTX_set_msg_callback.pod
DEPEND[man/man3/SSL_CTX_set_msg_callback.3]=man3/SSL_CTX_set_msg_callback.pod
GENERATE[man/man3/SSL_CTX_set_msg_callback.3]=man3/SSL_CTX_set_msg_callback.pod
DEPEND[html/man3/SSL_CTX_set_num_tickets.html]=man3/SSL_CTX_set_num_tickets.pod
GENERATE[html/man3/SSL_CTX_set_num_tickets.html]=man3/SSL_CTX_set_num_tickets.pod
DEPEND[man/man3/SSL_CTX_set_num_tickets.3]=man3/SSL_CTX_set_num_tickets.pod
GENERATE[man/man3/SSL_CTX_set_num_tickets.3]=man3/SSL_CTX_set_num_tickets.pod
DEPEND[html/man3/SSL_CTX_set_options.html]=man3/SSL_CTX_set_options.pod
GENERATE[html/man3/SSL_CTX_set_options.html]=man3/SSL_CTX_set_options.pod
DEPEND[man/man3/SSL_CTX_set_options.3]=man3/SSL_CTX_set_options.pod
GENERATE[man/man3/SSL_CTX_set_options.3]=man3/SSL_CTX_set_options.pod
DEPEND[html/man3/SSL_CTX_set_psk_client_callback.html]=man3/SSL_CTX_set_psk_client_callback.pod
GENERATE[html/man3/SSL_CTX_set_psk_client_callback.html]=man3/SSL_CTX_set_psk_client_callback.pod
DEPEND[man/man3/SSL_CTX_set_psk_client_callback.3]=man3/SSL_CTX_set_psk_client_callback.pod
GENERATE[man/man3/SSL_CTX_set_psk_client_callback.3]=man3/SSL_CTX_set_psk_client_callback.pod
DEPEND[html/man3/SSL_CTX_set_quiet_shutdown.html]=man3/SSL_CTX_set_quiet_shutdown.pod
GENERATE[html/man3/SSL_CTX_set_quiet_shutdown.html]=man3/SSL_CTX_set_quiet_shutdown.pod
DEPEND[man/man3/SSL_CTX_set_quiet_shutdown.3]=man3/SSL_CTX_set_quiet_shutdown.pod
GENERATE[man/man3/SSL_CTX_set_quiet_shutdown.3]=man3/SSL_CTX_set_quiet_shutdown.pod
DEPEND[html/man3/SSL_CTX_set_read_ahead.html]=man3/SSL_CTX_set_read_ahead.pod
GENERATE[html/man3/SSL_CTX_set_read_ahead.html]=man3/SSL_CTX_set_read_ahead.pod
DEPEND[man/man3/SSL_CTX_set_read_ahead.3]=man3/SSL_CTX_set_read_ahead.pod
GENERATE[man/man3/SSL_CTX_set_read_ahead.3]=man3/SSL_CTX_set_read_ahead.pod
DEPEND[html/man3/SSL_CTX_set_record_padding_callback.html]=man3/SSL_CTX_set_record_padding_callback.pod
GENERATE[html/man3/SSL_CTX_set_record_padding_callback.html]=man3/SSL_CTX_set_record_padding_callback.pod
DEPEND[man/man3/SSL_CTX_set_record_padding_callback.3]=man3/SSL_CTX_set_record_padding_callback.pod
GENERATE[man/man3/SSL_CTX_set_record_padding_callback.3]=man3/SSL_CTX_set_record_padding_callback.pod
DEPEND[html/man3/SSL_CTX_set_security_level.html]=man3/SSL_CTX_set_security_level.pod
GENERATE[html/man3/SSL_CTX_set_security_level.html]=man3/SSL_CTX_set_security_level.pod
DEPEND[man/man3/SSL_CTX_set_security_level.3]=man3/SSL_CTX_set_security_level.pod
GENERATE[man/man3/SSL_CTX_set_security_level.3]=man3/SSL_CTX_set_security_level.pod
DEPEND[html/man3/SSL_CTX_set_session_cache_mode.html]=man3/SSL_CTX_set_session_cache_mode.pod
GENERATE[html/man3/SSL_CTX_set_session_cache_mode.html]=man3/SSL_CTX_set_session_cache_mode.pod
DEPEND[man/man3/SSL_CTX_set_session_cache_mode.3]=man3/SSL_CTX_set_session_cache_mode.pod
GENERATE[man/man3/SSL_CTX_set_session_cache_mode.3]=man3/SSL_CTX_set_session_cache_mode.pod
DEPEND[html/man3/SSL_CTX_set_session_id_context.html]=man3/SSL_CTX_set_session_id_context.pod
GENERATE[html/man3/SSL_CTX_set_session_id_context.html]=man3/SSL_CTX_set_session_id_context.pod
DEPEND[man/man3/SSL_CTX_set_session_id_context.3]=man3/SSL_CTX_set_session_id_context.pod
GENERATE[man/man3/SSL_CTX_set_session_id_context.3]=man3/SSL_CTX_set_session_id_context.pod
DEPEND[html/man3/SSL_CTX_set_session_ticket_cb.html]=man3/SSL_CTX_set_session_ticket_cb.pod
GENERATE[html/man3/SSL_CTX_set_session_ticket_cb.html]=man3/SSL_CTX_set_session_ticket_cb.pod
DEPEND[man/man3/SSL_CTX_set_session_ticket_cb.3]=man3/SSL_CTX_set_session_ticket_cb.pod
GENERATE[man/man3/SSL_CTX_set_session_ticket_cb.3]=man3/SSL_CTX_set_session_ticket_cb.pod
DEPEND[html/man3/SSL_CTX_set_split_send_fragment.html]=man3/SSL_CTX_set_split_send_fragment.pod
GENERATE[html/man3/SSL_CTX_set_split_send_fragment.html]=man3/SSL_CTX_set_split_send_fragment.pod
DEPEND[man/man3/SSL_CTX_set_split_send_fragment.3]=man3/SSL_CTX_set_split_send_fragment.pod
GENERATE[man/man3/SSL_CTX_set_split_send_fragment.3]=man3/SSL_CTX_set_split_send_fragment.pod
DEPEND[html/man3/SSL_CTX_set_srp_password.html]=man3/SSL_CTX_set_srp_password.pod
GENERATE[html/man3/SSL_CTX_set_srp_password.html]=man3/SSL_CTX_set_srp_password.pod
DEPEND[man/man3/SSL_CTX_set_srp_password.3]=man3/SSL_CTX_set_srp_password.pod
GENERATE[man/man3/SSL_CTX_set_srp_password.3]=man3/SSL_CTX_set_srp_password.pod
DEPEND[html/man3/SSL_CTX_set_ssl_version.html]=man3/SSL_CTX_set_ssl_version.pod
GENERATE[html/man3/SSL_CTX_set_ssl_version.html]=man3/SSL_CTX_set_ssl_version.pod
DEPEND[man/man3/SSL_CTX_set_ssl_version.3]=man3/SSL_CTX_set_ssl_version.pod
GENERATE[man/man3/SSL_CTX_set_ssl_version.3]=man3/SSL_CTX_set_ssl_version.pod
DEPEND[html/man3/SSL_CTX_set_stateless_cookie_generate_cb.html]=man3/SSL_CTX_set_stateless_cookie_generate_cb.pod
GENERATE[html/man3/SSL_CTX_set_stateless_cookie_generate_cb.html]=man3/SSL_CTX_set_stateless_cookie_generate_cb.pod
DEPEND[man/man3/SSL_CTX_set_stateless_cookie_generate_cb.3]=man3/SSL_CTX_set_stateless_cookie_generate_cb.pod
GENERATE[man/man3/SSL_CTX_set_stateless_cookie_generate_cb.3]=man3/SSL_CTX_set_stateless_cookie_generate_cb.pod
DEPEND[html/man3/SSL_CTX_set_timeout.html]=man3/SSL_CTX_set_timeout.pod
GENERATE[html/man3/SSL_CTX_set_timeout.html]=man3/SSL_CTX_set_timeout.pod
DEPEND[man/man3/SSL_CTX_set_timeout.3]=man3/SSL_CTX_set_timeout.pod
GENERATE[man/man3/SSL_CTX_set_timeout.3]=man3/SSL_CTX_set_timeout.pod
DEPEND[html/man3/SSL_CTX_set_tlsext_servername_callback.html]=man3/SSL_CTX_set_tlsext_servername_callback.pod
GENERATE[html/man3/SSL_CTX_set_tlsext_servername_callback.html]=man3/SSL_CTX_set_tlsext_servername_callback.pod
DEPEND[man/man3/SSL_CTX_set_tlsext_servername_callback.3]=man3/SSL_CTX_set_tlsext_servername_callback.pod
GENERATE[man/man3/SSL_CTX_set_tlsext_servername_callback.3]=man3/SSL_CTX_set_tlsext_servername_callback.pod
DEPEND[html/man3/SSL_CTX_set_tlsext_status_cb.html]=man3/SSL_CTX_set_tlsext_status_cb.pod
GENERATE[html/man3/SSL_CTX_set_tlsext_status_cb.html]=man3/SSL_CTX_set_tlsext_status_cb.pod
DEPEND[man/man3/SSL_CTX_set_tlsext_status_cb.3]=man3/SSL_CTX_set_tlsext_status_cb.pod
GENERATE[man/man3/SSL_CTX_set_tlsext_status_cb.3]=man3/SSL_CTX_set_tlsext_status_cb.pod
DEPEND[html/man3/SSL_CTX_set_tlsext_ticket_key_cb.html]=man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
GENERATE[html/man3/SSL_CTX_set_tlsext_ticket_key_cb.html]=man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
DEPEND[man/man3/SSL_CTX_set_tlsext_ticket_key_cb.3]=man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
GENERATE[man/man3/SSL_CTX_set_tlsext_ticket_key_cb.3]=man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
DEPEND[html/man3/SSL_CTX_set_tlsext_use_srtp.html]=man3/SSL_CTX_set_tlsext_use_srtp.pod
GENERATE[html/man3/SSL_CTX_set_tlsext_use_srtp.html]=man3/SSL_CTX_set_tlsext_use_srtp.pod
DEPEND[man/man3/SSL_CTX_set_tlsext_use_srtp.3]=man3/SSL_CTX_set_tlsext_use_srtp.pod
GENERATE[man/man3/SSL_CTX_set_tlsext_use_srtp.3]=man3/SSL_CTX_set_tlsext_use_srtp.pod
DEPEND[html/man3/SSL_CTX_set_tmp_dh_callback.html]=man3/SSL_CTX_set_tmp_dh_callback.pod
GENERATE[html/man3/SSL_CTX_set_tmp_dh_callback.html]=man3/SSL_CTX_set_tmp_dh_callback.pod
DEPEND[man/man3/SSL_CTX_set_tmp_dh_callback.3]=man3/SSL_CTX_set_tmp_dh_callback.pod
GENERATE[man/man3/SSL_CTX_set_tmp_dh_callback.3]=man3/SSL_CTX_set_tmp_dh_callback.pod
DEPEND[html/man3/SSL_CTX_set_tmp_ecdh.html]=man3/SSL_CTX_set_tmp_ecdh.pod
GENERATE[html/man3/SSL_CTX_set_tmp_ecdh.html]=man3/SSL_CTX_set_tmp_ecdh.pod
DEPEND[man/man3/SSL_CTX_set_tmp_ecdh.3]=man3/SSL_CTX_set_tmp_ecdh.pod
GENERATE[man/man3/SSL_CTX_set_tmp_ecdh.3]=man3/SSL_CTX_set_tmp_ecdh.pod
DEPEND[html/man3/SSL_CTX_set_verify.html]=man3/SSL_CTX_set_verify.pod
GENERATE[html/man3/SSL_CTX_set_verify.html]=man3/SSL_CTX_set_verify.pod
DEPEND[man/man3/SSL_CTX_set_verify.3]=man3/SSL_CTX_set_verify.pod
GENERATE[man/man3/SSL_CTX_set_verify.3]=man3/SSL_CTX_set_verify.pod
DEPEND[html/man3/SSL_CTX_use_certificate.html]=man3/SSL_CTX_use_certificate.pod
GENERATE[html/man3/SSL_CTX_use_certificate.html]=man3/SSL_CTX_use_certificate.pod
DEPEND[man/man3/SSL_CTX_use_certificate.3]=man3/SSL_CTX_use_certificate.pod
GENERATE[man/man3/SSL_CTX_use_certificate.3]=man3/SSL_CTX_use_certificate.pod
DEPEND[html/man3/SSL_CTX_use_psk_identity_hint.html]=man3/SSL_CTX_use_psk_identity_hint.pod
GENERATE[html/man3/SSL_CTX_use_psk_identity_hint.html]=man3/SSL_CTX_use_psk_identity_hint.pod
DEPEND[man/man3/SSL_CTX_use_psk_identity_hint.3]=man3/SSL_CTX_use_psk_identity_hint.pod
GENERATE[man/man3/SSL_CTX_use_psk_identity_hint.3]=man3/SSL_CTX_use_psk_identity_hint.pod
DEPEND[html/man3/SSL_CTX_use_serverinfo.html]=man3/SSL_CTX_use_serverinfo.pod
GENERATE[html/man3/SSL_CTX_use_serverinfo.html]=man3/SSL_CTX_use_serverinfo.pod
DEPEND[man/man3/SSL_CTX_use_serverinfo.3]=man3/SSL_CTX_use_serverinfo.pod
GENERATE[man/man3/SSL_CTX_use_serverinfo.3]=man3/SSL_CTX_use_serverinfo.pod
DEPEND[html/man3/SSL_SESSION_free.html]=man3/SSL_SESSION_free.pod
GENERATE[html/man3/SSL_SESSION_free.html]=man3/SSL_SESSION_free.pod
DEPEND[man/man3/SSL_SESSION_free.3]=man3/SSL_SESSION_free.pod
GENERATE[man/man3/SSL_SESSION_free.3]=man3/SSL_SESSION_free.pod
DEPEND[html/man3/SSL_SESSION_get0_cipher.html]=man3/SSL_SESSION_get0_cipher.pod
GENERATE[html/man3/SSL_SESSION_get0_cipher.html]=man3/SSL_SESSION_get0_cipher.pod
DEPEND[man/man3/SSL_SESSION_get0_cipher.3]=man3/SSL_SESSION_get0_cipher.pod
GENERATE[man/man3/SSL_SESSION_get0_cipher.3]=man3/SSL_SESSION_get0_cipher.pod
DEPEND[html/man3/SSL_SESSION_get0_hostname.html]=man3/SSL_SESSION_get0_hostname.pod
GENERATE[html/man3/SSL_SESSION_get0_hostname.html]=man3/SSL_SESSION_get0_hostname.pod
DEPEND[man/man3/SSL_SESSION_get0_hostname.3]=man3/SSL_SESSION_get0_hostname.pod
GENERATE[man/man3/SSL_SESSION_get0_hostname.3]=man3/SSL_SESSION_get0_hostname.pod
DEPEND[html/man3/SSL_SESSION_get0_id_context.html]=man3/SSL_SESSION_get0_id_context.pod
GENERATE[html/man3/SSL_SESSION_get0_id_context.html]=man3/SSL_SESSION_get0_id_context.pod
DEPEND[man/man3/SSL_SESSION_get0_id_context.3]=man3/SSL_SESSION_get0_id_context.pod
GENERATE[man/man3/SSL_SESSION_get0_id_context.3]=man3/SSL_SESSION_get0_id_context.pod
DEPEND[html/man3/SSL_SESSION_get0_peer.html]=man3/SSL_SESSION_get0_peer.pod
GENERATE[html/man3/SSL_SESSION_get0_peer.html]=man3/SSL_SESSION_get0_peer.pod
DEPEND[man/man3/SSL_SESSION_get0_peer.3]=man3/SSL_SESSION_get0_peer.pod
GENERATE[man/man3/SSL_SESSION_get0_peer.3]=man3/SSL_SESSION_get0_peer.pod
DEPEND[html/man3/SSL_SESSION_get_compress_id.html]=man3/SSL_SESSION_get_compress_id.pod
GENERATE[html/man3/SSL_SESSION_get_compress_id.html]=man3/SSL_SESSION_get_compress_id.pod
DEPEND[man/man3/SSL_SESSION_get_compress_id.3]=man3/SSL_SESSION_get_compress_id.pod
GENERATE[man/man3/SSL_SESSION_get_compress_id.3]=man3/SSL_SESSION_get_compress_id.pod
DEPEND[html/man3/SSL_SESSION_get_protocol_version.html]=man3/SSL_SESSION_get_protocol_version.pod
GENERATE[html/man3/SSL_SESSION_get_protocol_version.html]=man3/SSL_SESSION_get_protocol_version.pod
DEPEND[man/man3/SSL_SESSION_get_protocol_version.3]=man3/SSL_SESSION_get_protocol_version.pod
GENERATE[man/man3/SSL_SESSION_get_protocol_version.3]=man3/SSL_SESSION_get_protocol_version.pod
DEPEND[html/man3/SSL_SESSION_get_time.html]=man3/SSL_SESSION_get_time.pod
GENERATE[html/man3/SSL_SESSION_get_time.html]=man3/SSL_SESSION_get_time.pod
DEPEND[man/man3/SSL_SESSION_get_time.3]=man3/SSL_SESSION_get_time.pod
GENERATE[man/man3/SSL_SESSION_get_time.3]=man3/SSL_SESSION_get_time.pod
DEPEND[html/man3/SSL_SESSION_has_ticket.html]=man3/SSL_SESSION_has_ticket.pod
GENERATE[html/man3/SSL_SESSION_has_ticket.html]=man3/SSL_SESSION_has_ticket.pod
DEPEND[man/man3/SSL_SESSION_has_ticket.3]=man3/SSL_SESSION_has_ticket.pod
GENERATE[man/man3/SSL_SESSION_has_ticket.3]=man3/SSL_SESSION_has_ticket.pod
DEPEND[html/man3/SSL_SESSION_is_resumable.html]=man3/SSL_SESSION_is_resumable.pod
GENERATE[html/man3/SSL_SESSION_is_resumable.html]=man3/SSL_SESSION_is_resumable.pod
DEPEND[man/man3/SSL_SESSION_is_resumable.3]=man3/SSL_SESSION_is_resumable.pod
GENERATE[man/man3/SSL_SESSION_is_resumable.3]=man3/SSL_SESSION_is_resumable.pod
DEPEND[html/man3/SSL_SESSION_print.html]=man3/SSL_SESSION_print.pod
GENERATE[html/man3/SSL_SESSION_print.html]=man3/SSL_SESSION_print.pod
DEPEND[man/man3/SSL_SESSION_print.3]=man3/SSL_SESSION_print.pod
GENERATE[man/man3/SSL_SESSION_print.3]=man3/SSL_SESSION_print.pod
DEPEND[html/man3/SSL_SESSION_set1_id.html]=man3/SSL_SESSION_set1_id.pod
GENERATE[html/man3/SSL_SESSION_set1_id.html]=man3/SSL_SESSION_set1_id.pod
DEPEND[man/man3/SSL_SESSION_set1_id.3]=man3/SSL_SESSION_set1_id.pod
GENERATE[man/man3/SSL_SESSION_set1_id.3]=man3/SSL_SESSION_set1_id.pod
DEPEND[html/man3/SSL_accept.html]=man3/SSL_accept.pod
GENERATE[html/man3/SSL_accept.html]=man3/SSL_accept.pod
DEPEND[man/man3/SSL_accept.3]=man3/SSL_accept.pod
GENERATE[man/man3/SSL_accept.3]=man3/SSL_accept.pod
DEPEND[html/man3/SSL_alert_type_string.html]=man3/SSL_alert_type_string.pod
GENERATE[html/man3/SSL_alert_type_string.html]=man3/SSL_alert_type_string.pod
DEPEND[man/man3/SSL_alert_type_string.3]=man3/SSL_alert_type_string.pod
GENERATE[man/man3/SSL_alert_type_string.3]=man3/SSL_alert_type_string.pod
DEPEND[html/man3/SSL_alloc_buffers.html]=man3/SSL_alloc_buffers.pod
GENERATE[html/man3/SSL_alloc_buffers.html]=man3/SSL_alloc_buffers.pod
DEPEND[man/man3/SSL_alloc_buffers.3]=man3/SSL_alloc_buffers.pod
GENERATE[man/man3/SSL_alloc_buffers.3]=man3/SSL_alloc_buffers.pod
DEPEND[html/man3/SSL_check_chain.html]=man3/SSL_check_chain.pod
GENERATE[html/man3/SSL_check_chain.html]=man3/SSL_check_chain.pod
DEPEND[man/man3/SSL_check_chain.3]=man3/SSL_check_chain.pod
GENERATE[man/man3/SSL_check_chain.3]=man3/SSL_check_chain.pod
DEPEND[html/man3/SSL_clear.html]=man3/SSL_clear.pod
GENERATE[html/man3/SSL_clear.html]=man3/SSL_clear.pod
DEPEND[man/man3/SSL_clear.3]=man3/SSL_clear.pod
GENERATE[man/man3/SSL_clear.3]=man3/SSL_clear.pod
DEPEND[html/man3/SSL_connect.html]=man3/SSL_connect.pod
GENERATE[html/man3/SSL_connect.html]=man3/SSL_connect.pod
DEPEND[man/man3/SSL_connect.3]=man3/SSL_connect.pod
GENERATE[man/man3/SSL_connect.3]=man3/SSL_connect.pod
DEPEND[html/man3/SSL_do_handshake.html]=man3/SSL_do_handshake.pod
GENERATE[html/man3/SSL_do_handshake.html]=man3/SSL_do_handshake.pod
DEPEND[man/man3/SSL_do_handshake.3]=man3/SSL_do_handshake.pod
GENERATE[man/man3/SSL_do_handshake.3]=man3/SSL_do_handshake.pod
DEPEND[html/man3/SSL_export_keying_material.html]=man3/SSL_export_keying_material.pod
GENERATE[html/man3/SSL_export_keying_material.html]=man3/SSL_export_keying_material.pod
DEPEND[man/man3/SSL_export_keying_material.3]=man3/SSL_export_keying_material.pod
GENERATE[man/man3/SSL_export_keying_material.3]=man3/SSL_export_keying_material.pod
DEPEND[html/man3/SSL_extension_supported.html]=man3/SSL_extension_supported.pod
GENERATE[html/man3/SSL_extension_supported.html]=man3/SSL_extension_supported.pod
DEPEND[man/man3/SSL_extension_supported.3]=man3/SSL_extension_supported.pod
GENERATE[man/man3/SSL_extension_supported.3]=man3/SSL_extension_supported.pod
DEPEND[html/man3/SSL_free.html]=man3/SSL_free.pod
GENERATE[html/man3/SSL_free.html]=man3/SSL_free.pod
DEPEND[man/man3/SSL_free.3]=man3/SSL_free.pod
GENERATE[man/man3/SSL_free.3]=man3/SSL_free.pod
DEPEND[html/man3/SSL_get0_peer_scts.html]=man3/SSL_get0_peer_scts.pod
GENERATE[html/man3/SSL_get0_peer_scts.html]=man3/SSL_get0_peer_scts.pod
DEPEND[man/man3/SSL_get0_peer_scts.3]=man3/SSL_get0_peer_scts.pod
GENERATE[man/man3/SSL_get0_peer_scts.3]=man3/SSL_get0_peer_scts.pod
DEPEND[html/man3/SSL_get_SSL_CTX.html]=man3/SSL_get_SSL_CTX.pod
GENERATE[html/man3/SSL_get_SSL_CTX.html]=man3/SSL_get_SSL_CTX.pod
DEPEND[man/man3/SSL_get_SSL_CTX.3]=man3/SSL_get_SSL_CTX.pod
GENERATE[man/man3/SSL_get_SSL_CTX.3]=man3/SSL_get_SSL_CTX.pod
DEPEND[html/man3/SSL_get_all_async_fds.html]=man3/SSL_get_all_async_fds.pod
GENERATE[html/man3/SSL_get_all_async_fds.html]=man3/SSL_get_all_async_fds.pod
DEPEND[man/man3/SSL_get_all_async_fds.3]=man3/SSL_get_all_async_fds.pod
GENERATE[man/man3/SSL_get_all_async_fds.3]=man3/SSL_get_all_async_fds.pod
DEPEND[html/man3/SSL_get_certificate.html]=man3/SSL_get_certificate.pod
GENERATE[html/man3/SSL_get_certificate.html]=man3/SSL_get_certificate.pod
DEPEND[man/man3/SSL_get_certificate.3]=man3/SSL_get_certificate.pod
GENERATE[man/man3/SSL_get_certificate.3]=man3/SSL_get_certificate.pod
DEPEND[html/man3/SSL_get_ciphers.html]=man3/SSL_get_ciphers.pod
GENERATE[html/man3/SSL_get_ciphers.html]=man3/SSL_get_ciphers.pod
DEPEND[man/man3/SSL_get_ciphers.3]=man3/SSL_get_ciphers.pod
GENERATE[man/man3/SSL_get_ciphers.3]=man3/SSL_get_ciphers.pod
DEPEND[html/man3/SSL_get_client_random.html]=man3/SSL_get_client_random.pod
GENERATE[html/man3/SSL_get_client_random.html]=man3/SSL_get_client_random.pod
DEPEND[man/man3/SSL_get_client_random.3]=man3/SSL_get_client_random.pod
GENERATE[man/man3/SSL_get_client_random.3]=man3/SSL_get_client_random.pod
DEPEND[html/man3/SSL_get_current_cipher.html]=man3/SSL_get_current_cipher.pod
GENERATE[html/man3/SSL_get_current_cipher.html]=man3/SSL_get_current_cipher.pod
DEPEND[man/man3/SSL_get_current_cipher.3]=man3/SSL_get_current_cipher.pod
GENERATE[man/man3/SSL_get_current_cipher.3]=man3/SSL_get_current_cipher.pod
DEPEND[html/man3/SSL_get_default_timeout.html]=man3/SSL_get_default_timeout.pod
GENERATE[html/man3/SSL_get_default_timeout.html]=man3/SSL_get_default_timeout.pod
DEPEND[man/man3/SSL_get_default_timeout.3]=man3/SSL_get_default_timeout.pod
GENERATE[man/man3/SSL_get_default_timeout.3]=man3/SSL_get_default_timeout.pod
DEPEND[html/man3/SSL_get_error.html]=man3/SSL_get_error.pod
GENERATE[html/man3/SSL_get_error.html]=man3/SSL_get_error.pod
DEPEND[man/man3/SSL_get_error.3]=man3/SSL_get_error.pod
GENERATE[man/man3/SSL_get_error.3]=man3/SSL_get_error.pod
DEPEND[html/man3/SSL_get_extms_support.html]=man3/SSL_get_extms_support.pod
GENERATE[html/man3/SSL_get_extms_support.html]=man3/SSL_get_extms_support.pod
DEPEND[man/man3/SSL_get_extms_support.3]=man3/SSL_get_extms_support.pod
GENERATE[man/man3/SSL_get_extms_support.3]=man3/SSL_get_extms_support.pod
DEPEND[html/man3/SSL_get_fd.html]=man3/SSL_get_fd.pod
GENERATE[html/man3/SSL_get_fd.html]=man3/SSL_get_fd.pod
DEPEND[man/man3/SSL_get_fd.3]=man3/SSL_get_fd.pod
GENERATE[man/man3/SSL_get_fd.3]=man3/SSL_get_fd.pod
DEPEND[html/man3/SSL_get_peer_cert_chain.html]=man3/SSL_get_peer_cert_chain.pod
GENERATE[html/man3/SSL_get_peer_cert_chain.html]=man3/SSL_get_peer_cert_chain.pod
DEPEND[man/man3/SSL_get_peer_cert_chain.3]=man3/SSL_get_peer_cert_chain.pod
GENERATE[man/man3/SSL_get_peer_cert_chain.3]=man3/SSL_get_peer_cert_chain.pod
DEPEND[html/man3/SSL_get_peer_certificate.html]=man3/SSL_get_peer_certificate.pod
GENERATE[html/man3/SSL_get_peer_certificate.html]=man3/SSL_get_peer_certificate.pod
DEPEND[man/man3/SSL_get_peer_certificate.3]=man3/SSL_get_peer_certificate.pod
GENERATE[man/man3/SSL_get_peer_certificate.3]=man3/SSL_get_peer_certificate.pod
DEPEND[html/man3/SSL_get_peer_signature_nid.html]=man3/SSL_get_peer_signature_nid.pod
GENERATE[html/man3/SSL_get_peer_signature_nid.html]=man3/SSL_get_peer_signature_nid.pod
DEPEND[man/man3/SSL_get_peer_signature_nid.3]=man3/SSL_get_peer_signature_nid.pod
GENERATE[man/man3/SSL_get_peer_signature_nid.3]=man3/SSL_get_peer_signature_nid.pod
DEPEND[html/man3/SSL_get_peer_tmp_key.html]=man3/SSL_get_peer_tmp_key.pod
GENERATE[html/man3/SSL_get_peer_tmp_key.html]=man3/SSL_get_peer_tmp_key.pod
DEPEND[man/man3/SSL_get_peer_tmp_key.3]=man3/SSL_get_peer_tmp_key.pod
GENERATE[man/man3/SSL_get_peer_tmp_key.3]=man3/SSL_get_peer_tmp_key.pod
DEPEND[html/man3/SSL_get_psk_identity.html]=man3/SSL_get_psk_identity.pod
GENERATE[html/man3/SSL_get_psk_identity.html]=man3/SSL_get_psk_identity.pod
DEPEND[man/man3/SSL_get_psk_identity.3]=man3/SSL_get_psk_identity.pod
GENERATE[man/man3/SSL_get_psk_identity.3]=man3/SSL_get_psk_identity.pod
DEPEND[html/man3/SSL_get_rbio.html]=man3/SSL_get_rbio.pod
GENERATE[html/man3/SSL_get_rbio.html]=man3/SSL_get_rbio.pod
DEPEND[man/man3/SSL_get_rbio.3]=man3/SSL_get_rbio.pod
GENERATE[man/man3/SSL_get_rbio.3]=man3/SSL_get_rbio.pod
DEPEND[html/man3/SSL_get_session.html]=man3/SSL_get_session.pod
GENERATE[html/man3/SSL_get_session.html]=man3/SSL_get_session.pod
DEPEND[man/man3/SSL_get_session.3]=man3/SSL_get_session.pod
GENERATE[man/man3/SSL_get_session.3]=man3/SSL_get_session.pod
DEPEND[html/man3/SSL_get_shared_sigalgs.html]=man3/SSL_get_shared_sigalgs.pod
GENERATE[html/man3/SSL_get_shared_sigalgs.html]=man3/SSL_get_shared_sigalgs.pod
DEPEND[man/man3/SSL_get_shared_sigalgs.3]=man3/SSL_get_shared_sigalgs.pod
GENERATE[man/man3/SSL_get_shared_sigalgs.3]=man3/SSL_get_shared_sigalgs.pod
DEPEND[html/man3/SSL_get_verify_result.html]=man3/SSL_get_verify_result.pod
GENERATE[html/man3/SSL_get_verify_result.html]=man3/SSL_get_verify_result.pod
DEPEND[man/man3/SSL_get_verify_result.3]=man3/SSL_get_verify_result.pod
GENERATE[man/man3/SSL_get_verify_result.3]=man3/SSL_get_verify_result.pod
DEPEND[html/man3/SSL_get_version.html]=man3/SSL_get_version.pod
GENERATE[html/man3/SSL_get_version.html]=man3/SSL_get_version.pod
DEPEND[man/man3/SSL_get_version.3]=man3/SSL_get_version.pod
GENERATE[man/man3/SSL_get_version.3]=man3/SSL_get_version.pod
DEPEND[html/man3/SSL_group_to_name.html]=man3/SSL_group_to_name.pod
GENERATE[html/man3/SSL_group_to_name.html]=man3/SSL_group_to_name.pod
DEPEND[man/man3/SSL_group_to_name.3]=man3/SSL_group_to_name.pod
GENERATE[man/man3/SSL_group_to_name.3]=man3/SSL_group_to_name.pod
DEPEND[html/man3/SSL_in_init.html]=man3/SSL_in_init.pod
GENERATE[html/man3/SSL_in_init.html]=man3/SSL_in_init.pod
DEPEND[man/man3/SSL_in_init.3]=man3/SSL_in_init.pod
GENERATE[man/man3/SSL_in_init.3]=man3/SSL_in_init.pod
DEPEND[html/man3/SSL_key_update.html]=man3/SSL_key_update.pod
GENERATE[html/man3/SSL_key_update.html]=man3/SSL_key_update.pod
DEPEND[man/man3/SSL_key_update.3]=man3/SSL_key_update.pod
GENERATE[man/man3/SSL_key_update.3]=man3/SSL_key_update.pod
DEPEND[html/man3/SSL_library_init.html]=man3/SSL_library_init.pod
GENERATE[html/man3/SSL_library_init.html]=man3/SSL_library_init.pod
DEPEND[man/man3/SSL_library_init.3]=man3/SSL_library_init.pod
GENERATE[man/man3/SSL_library_init.3]=man3/SSL_library_init.pod
DEPEND[html/man3/SSL_load_client_CA_file.html]=man3/SSL_load_client_CA_file.pod
GENERATE[html/man3/SSL_load_client_CA_file.html]=man3/SSL_load_client_CA_file.pod
DEPEND[man/man3/SSL_load_client_CA_file.3]=man3/SSL_load_client_CA_file.pod
GENERATE[man/man3/SSL_load_client_CA_file.3]=man3/SSL_load_client_CA_file.pod
DEPEND[html/man3/SSL_new.html]=man3/SSL_new.pod
GENERATE[html/man3/SSL_new.html]=man3/SSL_new.pod
DEPEND[man/man3/SSL_new.3]=man3/SSL_new.pod
GENERATE[man/man3/SSL_new.3]=man3/SSL_new.pod
DEPEND[html/man3/SSL_pending.html]=man3/SSL_pending.pod
GENERATE[html/man3/SSL_pending.html]=man3/SSL_pending.pod
DEPEND[man/man3/SSL_pending.3]=man3/SSL_pending.pod
GENERATE[man/man3/SSL_pending.3]=man3/SSL_pending.pod
DEPEND[html/man3/SSL_read.html]=man3/SSL_read.pod
GENERATE[html/man3/SSL_read.html]=man3/SSL_read.pod
DEPEND[man/man3/SSL_read.3]=man3/SSL_read.pod
GENERATE[man/man3/SSL_read.3]=man3/SSL_read.pod
DEPEND[html/man3/SSL_read_early_data.html]=man3/SSL_read_early_data.pod
GENERATE[html/man3/SSL_read_early_data.html]=man3/SSL_read_early_data.pod
DEPEND[man/man3/SSL_read_early_data.3]=man3/SSL_read_early_data.pod
GENERATE[man/man3/SSL_read_early_data.3]=man3/SSL_read_early_data.pod
DEPEND[html/man3/SSL_rstate_string.html]=man3/SSL_rstate_string.pod
GENERATE[html/man3/SSL_rstate_string.html]=man3/SSL_rstate_string.pod
DEPEND[man/man3/SSL_rstate_string.3]=man3/SSL_rstate_string.pod
GENERATE[man/man3/SSL_rstate_string.3]=man3/SSL_rstate_string.pod
DEPEND[html/man3/SSL_session_reused.html]=man3/SSL_session_reused.pod
GENERATE[html/man3/SSL_session_reused.html]=man3/SSL_session_reused.pod
DEPEND[man/man3/SSL_session_reused.3]=man3/SSL_session_reused.pod
GENERATE[man/man3/SSL_session_reused.3]=man3/SSL_session_reused.pod
DEPEND[html/man3/SSL_set1_host.html]=man3/SSL_set1_host.pod
GENERATE[html/man3/SSL_set1_host.html]=man3/SSL_set1_host.pod
DEPEND[man/man3/SSL_set1_host.3]=man3/SSL_set1_host.pod
GENERATE[man/man3/SSL_set1_host.3]=man3/SSL_set1_host.pod
DEPEND[html/man3/SSL_set_async_callback.html]=man3/SSL_set_async_callback.pod
GENERATE[html/man3/SSL_set_async_callback.html]=man3/SSL_set_async_callback.pod
DEPEND[man/man3/SSL_set_async_callback.3]=man3/SSL_set_async_callback.pod
GENERATE[man/man3/SSL_set_async_callback.3]=man3/SSL_set_async_callback.pod
DEPEND[html/man3/SSL_set_bio.html]=man3/SSL_set_bio.pod
GENERATE[html/man3/SSL_set_bio.html]=man3/SSL_set_bio.pod
DEPEND[man/man3/SSL_set_bio.3]=man3/SSL_set_bio.pod
GENERATE[man/man3/SSL_set_bio.3]=man3/SSL_set_bio.pod
DEPEND[html/man3/SSL_set_connect_state.html]=man3/SSL_set_connect_state.pod
GENERATE[html/man3/SSL_set_connect_state.html]=man3/SSL_set_connect_state.pod
DEPEND[man/man3/SSL_set_connect_state.3]=man3/SSL_set_connect_state.pod
GENERATE[man/man3/SSL_set_connect_state.3]=man3/SSL_set_connect_state.pod
DEPEND[html/man3/SSL_set_fd.html]=man3/SSL_set_fd.pod
GENERATE[html/man3/SSL_set_fd.html]=man3/SSL_set_fd.pod
DEPEND[man/man3/SSL_set_fd.3]=man3/SSL_set_fd.pod
GENERATE[man/man3/SSL_set_fd.3]=man3/SSL_set_fd.pod
DEPEND[html/man3/SSL_set_retry_verify.html]=man3/SSL_set_retry_verify.pod
GENERATE[html/man3/SSL_set_retry_verify.html]=man3/SSL_set_retry_verify.pod
DEPEND[man/man3/SSL_set_retry_verify.3]=man3/SSL_set_retry_verify.pod
GENERATE[man/man3/SSL_set_retry_verify.3]=man3/SSL_set_retry_verify.pod
DEPEND[html/man3/SSL_set_session.html]=man3/SSL_set_session.pod
GENERATE[html/man3/SSL_set_session.html]=man3/SSL_set_session.pod
DEPEND[man/man3/SSL_set_session.3]=man3/SSL_set_session.pod
GENERATE[man/man3/SSL_set_session.3]=man3/SSL_set_session.pod
DEPEND[html/man3/SSL_set_shutdown.html]=man3/SSL_set_shutdown.pod
GENERATE[html/man3/SSL_set_shutdown.html]=man3/SSL_set_shutdown.pod
DEPEND[man/man3/SSL_set_shutdown.3]=man3/SSL_set_shutdown.pod
GENERATE[man/man3/SSL_set_shutdown.3]=man3/SSL_set_shutdown.pod
DEPEND[html/man3/SSL_set_verify_result.html]=man3/SSL_set_verify_result.pod
GENERATE[html/man3/SSL_set_verify_result.html]=man3/SSL_set_verify_result.pod
DEPEND[man/man3/SSL_set_verify_result.3]=man3/SSL_set_verify_result.pod
GENERATE[man/man3/SSL_set_verify_result.3]=man3/SSL_set_verify_result.pod
DEPEND[html/man3/SSL_shutdown.html]=man3/SSL_shutdown.pod
GENERATE[html/man3/SSL_shutdown.html]=man3/SSL_shutdown.pod
DEPEND[man/man3/SSL_shutdown.3]=man3/SSL_shutdown.pod
GENERATE[man/man3/SSL_shutdown.3]=man3/SSL_shutdown.pod
DEPEND[html/man3/SSL_state_string.html]=man3/SSL_state_string.pod
GENERATE[html/man3/SSL_state_string.html]=man3/SSL_state_string.pod
DEPEND[man/man3/SSL_state_string.3]=man3/SSL_state_string.pod
GENERATE[man/man3/SSL_state_string.3]=man3/SSL_state_string.pod
DEPEND[html/man3/SSL_want.html]=man3/SSL_want.pod
GENERATE[html/man3/SSL_want.html]=man3/SSL_want.pod
DEPEND[man/man3/SSL_want.3]=man3/SSL_want.pod
GENERATE[man/man3/SSL_want.3]=man3/SSL_want.pod
DEPEND[html/man3/SSL_write.html]=man3/SSL_write.pod
GENERATE[html/man3/SSL_write.html]=man3/SSL_write.pod
DEPEND[man/man3/SSL_write.3]=man3/SSL_write.pod
GENERATE[man/man3/SSL_write.3]=man3/SSL_write.pod
DEPEND[html/man3/TS_RESP_CTX_new.html]=man3/TS_RESP_CTX_new.pod
GENERATE[html/man3/TS_RESP_CTX_new.html]=man3/TS_RESP_CTX_new.pod
DEPEND[man/man3/TS_RESP_CTX_new.3]=man3/TS_RESP_CTX_new.pod
GENERATE[man/man3/TS_RESP_CTX_new.3]=man3/TS_RESP_CTX_new.pod
DEPEND[html/man3/TS_VERIFY_CTX_set_certs.html]=man3/TS_VERIFY_CTX_set_certs.pod
GENERATE[html/man3/TS_VERIFY_CTX_set_certs.html]=man3/TS_VERIFY_CTX_set_certs.pod
DEPEND[man/man3/TS_VERIFY_CTX_set_certs.3]=man3/TS_VERIFY_CTX_set_certs.pod
GENERATE[man/man3/TS_VERIFY_CTX_set_certs.3]=man3/TS_VERIFY_CTX_set_certs.pod
DEPEND[html/man3/UI_STRING.html]=man3/UI_STRING.pod
GENERATE[html/man3/UI_STRING.html]=man3/UI_STRING.pod
DEPEND[man/man3/UI_STRING.3]=man3/UI_STRING.pod
GENERATE[man/man3/UI_STRING.3]=man3/UI_STRING.pod
DEPEND[html/man3/UI_UTIL_read_pw.html]=man3/UI_UTIL_read_pw.pod
GENERATE[html/man3/UI_UTIL_read_pw.html]=man3/UI_UTIL_read_pw.pod
DEPEND[man/man3/UI_UTIL_read_pw.3]=man3/UI_UTIL_read_pw.pod
GENERATE[man/man3/UI_UTIL_read_pw.3]=man3/UI_UTIL_read_pw.pod
DEPEND[html/man3/UI_create_method.html]=man3/UI_create_method.pod
GENERATE[html/man3/UI_create_method.html]=man3/UI_create_method.pod
DEPEND[man/man3/UI_create_method.3]=man3/UI_create_method.pod
GENERATE[man/man3/UI_create_method.3]=man3/UI_create_method.pod
DEPEND[html/man3/UI_new.html]=man3/UI_new.pod
GENERATE[html/man3/UI_new.html]=man3/UI_new.pod
DEPEND[man/man3/UI_new.3]=man3/UI_new.pod
GENERATE[man/man3/UI_new.3]=man3/UI_new.pod
DEPEND[html/man3/X509V3_get_d2i.html]=man3/X509V3_get_d2i.pod
GENERATE[html/man3/X509V3_get_d2i.html]=man3/X509V3_get_d2i.pod
DEPEND[man/man3/X509V3_get_d2i.3]=man3/X509V3_get_d2i.pod
GENERATE[man/man3/X509V3_get_d2i.3]=man3/X509V3_get_d2i.pod
DEPEND[html/man3/X509V3_set_ctx.html]=man3/X509V3_set_ctx.pod
GENERATE[html/man3/X509V3_set_ctx.html]=man3/X509V3_set_ctx.pod
DEPEND[man/man3/X509V3_set_ctx.3]=man3/X509V3_set_ctx.pod
GENERATE[man/man3/X509V3_set_ctx.3]=man3/X509V3_set_ctx.pod
DEPEND[html/man3/X509_ALGOR_dup.html]=man3/X509_ALGOR_dup.pod
GENERATE[html/man3/X509_ALGOR_dup.html]=man3/X509_ALGOR_dup.pod
DEPEND[man/man3/X509_ALGOR_dup.3]=man3/X509_ALGOR_dup.pod
GENERATE[man/man3/X509_ALGOR_dup.3]=man3/X509_ALGOR_dup.pod
DEPEND[html/man3/X509_CRL_get0_by_serial.html]=man3/X509_CRL_get0_by_serial.pod
GENERATE[html/man3/X509_CRL_get0_by_serial.html]=man3/X509_CRL_get0_by_serial.pod
DEPEND[man/man3/X509_CRL_get0_by_serial.3]=man3/X509_CRL_get0_by_serial.pod
GENERATE[man/man3/X509_CRL_get0_by_serial.3]=man3/X509_CRL_get0_by_serial.pod
DEPEND[html/man3/X509_EXTENSION_set_object.html]=man3/X509_EXTENSION_set_object.pod
GENERATE[html/man3/X509_EXTENSION_set_object.html]=man3/X509_EXTENSION_set_object.pod
DEPEND[man/man3/X509_EXTENSION_set_object.3]=man3/X509_EXTENSION_set_object.pod
GENERATE[man/man3/X509_EXTENSION_set_object.3]=man3/X509_EXTENSION_set_object.pod
DEPEND[html/man3/X509_LOOKUP.html]=man3/X509_LOOKUP.pod
GENERATE[html/man3/X509_LOOKUP.html]=man3/X509_LOOKUP.pod
DEPEND[man/man3/X509_LOOKUP.3]=man3/X509_LOOKUP.pod
GENERATE[man/man3/X509_LOOKUP.3]=man3/X509_LOOKUP.pod
DEPEND[html/man3/X509_LOOKUP_hash_dir.html]=man3/X509_LOOKUP_hash_dir.pod
GENERATE[html/man3/X509_LOOKUP_hash_dir.html]=man3/X509_LOOKUP_hash_dir.pod
DEPEND[man/man3/X509_LOOKUP_hash_dir.3]=man3/X509_LOOKUP_hash_dir.pod
GENERATE[man/man3/X509_LOOKUP_hash_dir.3]=man3/X509_LOOKUP_hash_dir.pod
DEPEND[html/man3/X509_LOOKUP_meth_new.html]=man3/X509_LOOKUP_meth_new.pod
GENERATE[html/man3/X509_LOOKUP_meth_new.html]=man3/X509_LOOKUP_meth_new.pod
DEPEND[man/man3/X509_LOOKUP_meth_new.3]=man3/X509_LOOKUP_meth_new.pod
GENERATE[man/man3/X509_LOOKUP_meth_new.3]=man3/X509_LOOKUP_meth_new.pod
DEPEND[html/man3/X509_NAME_ENTRY_get_object.html]=man3/X509_NAME_ENTRY_get_object.pod
GENERATE[html/man3/X509_NAME_ENTRY_get_object.html]=man3/X509_NAME_ENTRY_get_object.pod
DEPEND[man/man3/X509_NAME_ENTRY_get_object.3]=man3/X509_NAME_ENTRY_get_object.pod
GENERATE[man/man3/X509_NAME_ENTRY_get_object.3]=man3/X509_NAME_ENTRY_get_object.pod
DEPEND[html/man3/X509_NAME_add_entry_by_txt.html]=man3/X509_NAME_add_entry_by_txt.pod
GENERATE[html/man3/X509_NAME_add_entry_by_txt.html]=man3/X509_NAME_add_entry_by_txt.pod
DEPEND[man/man3/X509_NAME_add_entry_by_txt.3]=man3/X509_NAME_add_entry_by_txt.pod
GENERATE[man/man3/X509_NAME_add_entry_by_txt.3]=man3/X509_NAME_add_entry_by_txt.pod
DEPEND[html/man3/X509_NAME_get0_der.html]=man3/X509_NAME_get0_der.pod
GENERATE[html/man3/X509_NAME_get0_der.html]=man3/X509_NAME_get0_der.pod
DEPEND[man/man3/X509_NAME_get0_der.3]=man3/X509_NAME_get0_der.pod
GENERATE[man/man3/X509_NAME_get0_der.3]=man3/X509_NAME_get0_der.pod
DEPEND[html/man3/X509_NAME_get_index_by_NID.html]=man3/X509_NAME_get_index_by_NID.pod
GENERATE[html/man3/X509_NAME_get_index_by_NID.html]=man3/X509_NAME_get_index_by_NID.pod
DEPEND[man/man3/X509_NAME_get_index_by_NID.3]=man3/X509_NAME_get_index_by_NID.pod
GENERATE[man/man3/X509_NAME_get_index_by_NID.3]=man3/X509_NAME_get_index_by_NID.pod
DEPEND[html/man3/X509_NAME_print_ex.html]=man3/X509_NAME_print_ex.pod
GENERATE[html/man3/X509_NAME_print_ex.html]=man3/X509_NAME_print_ex.pod
DEPEND[man/man3/X509_NAME_print_ex.3]=man3/X509_NAME_print_ex.pod
GENERATE[man/man3/X509_NAME_print_ex.3]=man3/X509_NAME_print_ex.pod
DEPEND[html/man3/X509_PUBKEY_new.html]=man3/X509_PUBKEY_new.pod
GENERATE[html/man3/X509_PUBKEY_new.html]=man3/X509_PUBKEY_new.pod
DEPEND[man/man3/X509_PUBKEY_new.3]=man3/X509_PUBKEY_new.pod
GENERATE[man/man3/X509_PUBKEY_new.3]=man3/X509_PUBKEY_new.pod
DEPEND[html/man3/X509_SIG_get0.html]=man3/X509_SIG_get0.pod
GENERATE[html/man3/X509_SIG_get0.html]=man3/X509_SIG_get0.pod
DEPEND[man/man3/X509_SIG_get0.3]=man3/X509_SIG_get0.pod
GENERATE[man/man3/X509_SIG_get0.3]=man3/X509_SIG_get0.pod
DEPEND[html/man3/X509_STORE_CTX_get_error.html]=man3/X509_STORE_CTX_get_error.pod
GENERATE[html/man3/X509_STORE_CTX_get_error.html]=man3/X509_STORE_CTX_get_error.pod
DEPEND[man/man3/X509_STORE_CTX_get_error.3]=man3/X509_STORE_CTX_get_error.pod
GENERATE[man/man3/X509_STORE_CTX_get_error.3]=man3/X509_STORE_CTX_get_error.pod
DEPEND[html/man3/X509_STORE_CTX_new.html]=man3/X509_STORE_CTX_new.pod
GENERATE[html/man3/X509_STORE_CTX_new.html]=man3/X509_STORE_CTX_new.pod
DEPEND[man/man3/X509_STORE_CTX_new.3]=man3/X509_STORE_CTX_new.pod
GENERATE[man/man3/X509_STORE_CTX_new.3]=man3/X509_STORE_CTX_new.pod
DEPEND[html/man3/X509_STORE_CTX_set_verify_cb.html]=man3/X509_STORE_CTX_set_verify_cb.pod
GENERATE[html/man3/X509_STORE_CTX_set_verify_cb.html]=man3/X509_STORE_CTX_set_verify_cb.pod
DEPEND[man/man3/X509_STORE_CTX_set_verify_cb.3]=man3/X509_STORE_CTX_set_verify_cb.pod
GENERATE[man/man3/X509_STORE_CTX_set_verify_cb.3]=man3/X509_STORE_CTX_set_verify_cb.pod
DEPEND[html/man3/X509_STORE_add_cert.html]=man3/X509_STORE_add_cert.pod
GENERATE[html/man3/X509_STORE_add_cert.html]=man3/X509_STORE_add_cert.pod
DEPEND[man/man3/X509_STORE_add_cert.3]=man3/X509_STORE_add_cert.pod
GENERATE[man/man3/X509_STORE_add_cert.3]=man3/X509_STORE_add_cert.pod
DEPEND[html/man3/X509_STORE_get0_param.html]=man3/X509_STORE_get0_param.pod
GENERATE[html/man3/X509_STORE_get0_param.html]=man3/X509_STORE_get0_param.pod
DEPEND[man/man3/X509_STORE_get0_param.3]=man3/X509_STORE_get0_param.pod
GENERATE[man/man3/X509_STORE_get0_param.3]=man3/X509_STORE_get0_param.pod
DEPEND[html/man3/X509_STORE_new.html]=man3/X509_STORE_new.pod
GENERATE[html/man3/X509_STORE_new.html]=man3/X509_STORE_new.pod
DEPEND[man/man3/X509_STORE_new.3]=man3/X509_STORE_new.pod
GENERATE[man/man3/X509_STORE_new.3]=man3/X509_STORE_new.pod
DEPEND[html/man3/X509_STORE_set_verify_cb_func.html]=man3/X509_STORE_set_verify_cb_func.pod
GENERATE[html/man3/X509_STORE_set_verify_cb_func.html]=man3/X509_STORE_set_verify_cb_func.pod
DEPEND[man/man3/X509_STORE_set_verify_cb_func.3]=man3/X509_STORE_set_verify_cb_func.pod
GENERATE[man/man3/X509_STORE_set_verify_cb_func.3]=man3/X509_STORE_set_verify_cb_func.pod
DEPEND[html/man3/X509_VERIFY_PARAM_set_flags.html]=man3/X509_VERIFY_PARAM_set_flags.pod
GENERATE[html/man3/X509_VERIFY_PARAM_set_flags.html]=man3/X509_VERIFY_PARAM_set_flags.pod
DEPEND[man/man3/X509_VERIFY_PARAM_set_flags.3]=man3/X509_VERIFY_PARAM_set_flags.pod
GENERATE[man/man3/X509_VERIFY_PARAM_set_flags.3]=man3/X509_VERIFY_PARAM_set_flags.pod
DEPEND[html/man3/X509_add_cert.html]=man3/X509_add_cert.pod
GENERATE[html/man3/X509_add_cert.html]=man3/X509_add_cert.pod
DEPEND[man/man3/X509_add_cert.3]=man3/X509_add_cert.pod
GENERATE[man/man3/X509_add_cert.3]=man3/X509_add_cert.pod
DEPEND[html/man3/X509_check_ca.html]=man3/X509_check_ca.pod
GENERATE[html/man3/X509_check_ca.html]=man3/X509_check_ca.pod
DEPEND[man/man3/X509_check_ca.3]=man3/X509_check_ca.pod
GENERATE[man/man3/X509_check_ca.3]=man3/X509_check_ca.pod
DEPEND[html/man3/X509_check_host.html]=man3/X509_check_host.pod
GENERATE[html/man3/X509_check_host.html]=man3/X509_check_host.pod
DEPEND[man/man3/X509_check_host.3]=man3/X509_check_host.pod
GENERATE[man/man3/X509_check_host.3]=man3/X509_check_host.pod
DEPEND[html/man3/X509_check_issued.html]=man3/X509_check_issued.pod
GENERATE[html/man3/X509_check_issued.html]=man3/X509_check_issued.pod
DEPEND[man/man3/X509_check_issued.3]=man3/X509_check_issued.pod
GENERATE[man/man3/X509_check_issued.3]=man3/X509_check_issued.pod
DEPEND[html/man3/X509_check_private_key.html]=man3/X509_check_private_key.pod
GENERATE[html/man3/X509_check_private_key.html]=man3/X509_check_private_key.pod
DEPEND[man/man3/X509_check_private_key.3]=man3/X509_check_private_key.pod
GENERATE[man/man3/X509_check_private_key.3]=man3/X509_check_private_key.pod
DEPEND[html/man3/X509_check_purpose.html]=man3/X509_check_purpose.pod
GENERATE[html/man3/X509_check_purpose.html]=man3/X509_check_purpose.pod
DEPEND[man/man3/X509_check_purpose.3]=man3/X509_check_purpose.pod
GENERATE[man/man3/X509_check_purpose.3]=man3/X509_check_purpose.pod
DEPEND[html/man3/X509_cmp.html]=man3/X509_cmp.pod
GENERATE[html/man3/X509_cmp.html]=man3/X509_cmp.pod
DEPEND[man/man3/X509_cmp.3]=man3/X509_cmp.pod
GENERATE[man/man3/X509_cmp.3]=man3/X509_cmp.pod
DEPEND[html/man3/X509_cmp_time.html]=man3/X509_cmp_time.pod
GENERATE[html/man3/X509_cmp_time.html]=man3/X509_cmp_time.pod
DEPEND[man/man3/X509_cmp_time.3]=man3/X509_cmp_time.pod
GENERATE[man/man3/X509_cmp_time.3]=man3/X509_cmp_time.pod
DEPEND[html/man3/X509_digest.html]=man3/X509_digest.pod
GENERATE[html/man3/X509_digest.html]=man3/X509_digest.pod
DEPEND[man/man3/X509_digest.3]=man3/X509_digest.pod
GENERATE[man/man3/X509_digest.3]=man3/X509_digest.pod
DEPEND[html/man3/X509_dup.html]=man3/X509_dup.pod
GENERATE[html/man3/X509_dup.html]=man3/X509_dup.pod
DEPEND[man/man3/X509_dup.3]=man3/X509_dup.pod
GENERATE[man/man3/X509_dup.3]=man3/X509_dup.pod
DEPEND[html/man3/X509_get0_distinguishing_id.html]=man3/X509_get0_distinguishing_id.pod
GENERATE[html/man3/X509_get0_distinguishing_id.html]=man3/X509_get0_distinguishing_id.pod
DEPEND[man/man3/X509_get0_distinguishing_id.3]=man3/X509_get0_distinguishing_id.pod
GENERATE[man/man3/X509_get0_distinguishing_id.3]=man3/X509_get0_distinguishing_id.pod
DEPEND[html/man3/X509_get0_notBefore.html]=man3/X509_get0_notBefore.pod
GENERATE[html/man3/X509_get0_notBefore.html]=man3/X509_get0_notBefore.pod
DEPEND[man/man3/X509_get0_notBefore.3]=man3/X509_get0_notBefore.pod
GENERATE[man/man3/X509_get0_notBefore.3]=man3/X509_get0_notBefore.pod
DEPEND[html/man3/X509_get0_signature.html]=man3/X509_get0_signature.pod
GENERATE[html/man3/X509_get0_signature.html]=man3/X509_get0_signature.pod
DEPEND[man/man3/X509_get0_signature.3]=man3/X509_get0_signature.pod
GENERATE[man/man3/X509_get0_signature.3]=man3/X509_get0_signature.pod
DEPEND[html/man3/X509_get0_uids.html]=man3/X509_get0_uids.pod
GENERATE[html/man3/X509_get0_uids.html]=man3/X509_get0_uids.pod
DEPEND[man/man3/X509_get0_uids.3]=man3/X509_get0_uids.pod
GENERATE[man/man3/X509_get0_uids.3]=man3/X509_get0_uids.pod
DEPEND[html/man3/X509_get_extension_flags.html]=man3/X509_get_extension_flags.pod
GENERATE[html/man3/X509_get_extension_flags.html]=man3/X509_get_extension_flags.pod
DEPEND[man/man3/X509_get_extension_flags.3]=man3/X509_get_extension_flags.pod
GENERATE[man/man3/X509_get_extension_flags.3]=man3/X509_get_extension_flags.pod
DEPEND[html/man3/X509_get_pubkey.html]=man3/X509_get_pubkey.pod
GENERATE[html/man3/X509_get_pubkey.html]=man3/X509_get_pubkey.pod
DEPEND[man/man3/X509_get_pubkey.3]=man3/X509_get_pubkey.pod
GENERATE[man/man3/X509_get_pubkey.3]=man3/X509_get_pubkey.pod
DEPEND[html/man3/X509_get_serialNumber.html]=man3/X509_get_serialNumber.pod
GENERATE[html/man3/X509_get_serialNumber.html]=man3/X509_get_serialNumber.pod
DEPEND[man/man3/X509_get_serialNumber.3]=man3/X509_get_serialNumber.pod
GENERATE[man/man3/X509_get_serialNumber.3]=man3/X509_get_serialNumber.pod
DEPEND[html/man3/X509_get_subject_name.html]=man3/X509_get_subject_name.pod
GENERATE[html/man3/X509_get_subject_name.html]=man3/X509_get_subject_name.pod
DEPEND[man/man3/X509_get_subject_name.3]=man3/X509_get_subject_name.pod
GENERATE[man/man3/X509_get_subject_name.3]=man3/X509_get_subject_name.pod
DEPEND[html/man3/X509_get_version.html]=man3/X509_get_version.pod
GENERATE[html/man3/X509_get_version.html]=man3/X509_get_version.pod
DEPEND[man/man3/X509_get_version.3]=man3/X509_get_version.pod
GENERATE[man/man3/X509_get_version.3]=man3/X509_get_version.pod
DEPEND[html/man3/X509_load_http.html]=man3/X509_load_http.pod
GENERATE[html/man3/X509_load_http.html]=man3/X509_load_http.pod
DEPEND[man/man3/X509_load_http.3]=man3/X509_load_http.pod
GENERATE[man/man3/X509_load_http.3]=man3/X509_load_http.pod
DEPEND[html/man3/X509_new.html]=man3/X509_new.pod
GENERATE[html/man3/X509_new.html]=man3/X509_new.pod
DEPEND[man/man3/X509_new.3]=man3/X509_new.pod
GENERATE[man/man3/X509_new.3]=man3/X509_new.pod
DEPEND[html/man3/X509_sign.html]=man3/X509_sign.pod
GENERATE[html/man3/X509_sign.html]=man3/X509_sign.pod
DEPEND[man/man3/X509_sign.3]=man3/X509_sign.pod
GENERATE[man/man3/X509_sign.3]=man3/X509_sign.pod
DEPEND[html/man3/X509_verify.html]=man3/X509_verify.pod
GENERATE[html/man3/X509_verify.html]=man3/X509_verify.pod
DEPEND[man/man3/X509_verify.3]=man3/X509_verify.pod
GENERATE[man/man3/X509_verify.3]=man3/X509_verify.pod
DEPEND[html/man3/X509_verify_cert.html]=man3/X509_verify_cert.pod
GENERATE[html/man3/X509_verify_cert.html]=man3/X509_verify_cert.pod
DEPEND[man/man3/X509_verify_cert.3]=man3/X509_verify_cert.pod
GENERATE[man/man3/X509_verify_cert.3]=man3/X509_verify_cert.pod
DEPEND[html/man3/X509v3_get_ext_by_NID.html]=man3/X509v3_get_ext_by_NID.pod
GENERATE[html/man3/X509v3_get_ext_by_NID.html]=man3/X509v3_get_ext_by_NID.pod
DEPEND[man/man3/X509v3_get_ext_by_NID.3]=man3/X509v3_get_ext_by_NID.pod
GENERATE[man/man3/X509v3_get_ext_by_NID.3]=man3/X509v3_get_ext_by_NID.pod
DEPEND[html/man3/b2i_PVK_bio_ex.html]=man3/b2i_PVK_bio_ex.pod
GENERATE[html/man3/b2i_PVK_bio_ex.html]=man3/b2i_PVK_bio_ex.pod
DEPEND[man/man3/b2i_PVK_bio_ex.3]=man3/b2i_PVK_bio_ex.pod
GENERATE[man/man3/b2i_PVK_bio_ex.3]=man3/b2i_PVK_bio_ex.pod
DEPEND[html/man3/d2i_PKCS8PrivateKey_bio.html]=man3/d2i_PKCS8PrivateKey_bio.pod
GENERATE[html/man3/d2i_PKCS8PrivateKey_bio.html]=man3/d2i_PKCS8PrivateKey_bio.pod
DEPEND[man/man3/d2i_PKCS8PrivateKey_bio.3]=man3/d2i_PKCS8PrivateKey_bio.pod
GENERATE[man/man3/d2i_PKCS8PrivateKey_bio.3]=man3/d2i_PKCS8PrivateKey_bio.pod
DEPEND[html/man3/d2i_PrivateKey.html]=man3/d2i_PrivateKey.pod
GENERATE[html/man3/d2i_PrivateKey.html]=man3/d2i_PrivateKey.pod
DEPEND[man/man3/d2i_PrivateKey.3]=man3/d2i_PrivateKey.pod
GENERATE[man/man3/d2i_PrivateKey.3]=man3/d2i_PrivateKey.pod
DEPEND[html/man3/d2i_RSAPrivateKey.html]=man3/d2i_RSAPrivateKey.pod
GENERATE[html/man3/d2i_RSAPrivateKey.html]=man3/d2i_RSAPrivateKey.pod
DEPEND[man/man3/d2i_RSAPrivateKey.3]=man3/d2i_RSAPrivateKey.pod
GENERATE[man/man3/d2i_RSAPrivateKey.3]=man3/d2i_RSAPrivateKey.pod
DEPEND[html/man3/d2i_SSL_SESSION.html]=man3/d2i_SSL_SESSION.pod
GENERATE[html/man3/d2i_SSL_SESSION.html]=man3/d2i_SSL_SESSION.pod
DEPEND[man/man3/d2i_SSL_SESSION.3]=man3/d2i_SSL_SESSION.pod
GENERATE[man/man3/d2i_SSL_SESSION.3]=man3/d2i_SSL_SESSION.pod
DEPEND[html/man3/d2i_X509.html]=man3/d2i_X509.pod
GENERATE[html/man3/d2i_X509.html]=man3/d2i_X509.pod
DEPEND[man/man3/d2i_X509.3]=man3/d2i_X509.pod
GENERATE[man/man3/d2i_X509.3]=man3/d2i_X509.pod
DEPEND[html/man3/i2d_CMS_bio_stream.html]=man3/i2d_CMS_bio_stream.pod
GENERATE[html/man3/i2d_CMS_bio_stream.html]=man3/i2d_CMS_bio_stream.pod
DEPEND[man/man3/i2d_CMS_bio_stream.3]=man3/i2d_CMS_bio_stream.pod
GENERATE[man/man3/i2d_CMS_bio_stream.3]=man3/i2d_CMS_bio_stream.pod
DEPEND[html/man3/i2d_PKCS7_bio_stream.html]=man3/i2d_PKCS7_bio_stream.pod
GENERATE[html/man3/i2d_PKCS7_bio_stream.html]=man3/i2d_PKCS7_bio_stream.pod
DEPEND[man/man3/i2d_PKCS7_bio_stream.3]=man3/i2d_PKCS7_bio_stream.pod
GENERATE[man/man3/i2d_PKCS7_bio_stream.3]=man3/i2d_PKCS7_bio_stream.pod
DEPEND[html/man3/i2d_re_X509_tbs.html]=man3/i2d_re_X509_tbs.pod
GENERATE[html/man3/i2d_re_X509_tbs.html]=man3/i2d_re_X509_tbs.pod
DEPEND[man/man3/i2d_re_X509_tbs.3]=man3/i2d_re_X509_tbs.pod
GENERATE[man/man3/i2d_re_X509_tbs.3]=man3/i2d_re_X509_tbs.pod
DEPEND[html/man3/o2i_SCT_LIST.html]=man3/o2i_SCT_LIST.pod
GENERATE[html/man3/o2i_SCT_LIST.html]=man3/o2i_SCT_LIST.pod
DEPEND[man/man3/o2i_SCT_LIST.3]=man3/o2i_SCT_LIST.pod
GENERATE[man/man3/o2i_SCT_LIST.3]=man3/o2i_SCT_LIST.pod
DEPEND[html/man3/s2i_ASN1_IA5STRING.html]=man3/s2i_ASN1_IA5STRING.pod
GENERATE[html/man3/s2i_ASN1_IA5STRING.html]=man3/s2i_ASN1_IA5STRING.pod
DEPEND[man/man3/s2i_ASN1_IA5STRING.3]=man3/s2i_ASN1_IA5STRING.pod
GENERATE[man/man3/s2i_ASN1_IA5STRING.3]=man3/s2i_ASN1_IA5STRING.pod
IMAGEDOCS[man3]=
HTMLDOCS[man3]=html/man3/ADMISSIONS.html \
html/man3/ASN1_EXTERN_FUNCS.html \
html/man3/ASN1_INTEGER_get_int64.html \
html/man3/ASN1_INTEGER_new.html \
html/man3/ASN1_ITEM_lookup.html \
html/man3/ASN1_OBJECT_new.html \
html/man3/ASN1_STRING_TABLE_add.html \
html/man3/ASN1_STRING_length.html \
html/man3/ASN1_STRING_new.html \
html/man3/ASN1_STRING_print_ex.html \
html/man3/ASN1_TIME_set.html \
html/man3/ASN1_TYPE_get.html \
html/man3/ASN1_aux_cb.html \
html/man3/ASN1_generate_nconf.html \
html/man3/ASN1_item_d2i_bio.html \
html/man3/ASN1_item_new.html \
html/man3/ASN1_item_sign.html \
html/man3/ASYNC_WAIT_CTX_new.html \
html/man3/ASYNC_start_job.html \
html/man3/BF_encrypt.html \
html/man3/BIO_ADDR.html \
html/man3/BIO_ADDRINFO.html \
html/man3/BIO_connect.html \
html/man3/BIO_ctrl.html \
html/man3/BIO_f_base64.html \
html/man3/BIO_f_buffer.html \
html/man3/BIO_f_cipher.html \
html/man3/BIO_f_md.html \
html/man3/BIO_f_null.html \
html/man3/BIO_f_prefix.html \
html/man3/BIO_f_readbuffer.html \
html/man3/BIO_f_ssl.html \
html/man3/BIO_find_type.html \
html/man3/BIO_get_data.html \
html/man3/BIO_get_ex_new_index.html \
html/man3/BIO_meth_new.html \
html/man3/BIO_new.html \
html/man3/BIO_new_CMS.html \
html/man3/BIO_parse_hostserv.html \
html/man3/BIO_printf.html \
html/man3/BIO_push.html \
html/man3/BIO_read.html \
html/man3/BIO_s_accept.html \
html/man3/BIO_s_bio.html \
html/man3/BIO_s_connect.html \
html/man3/BIO_s_core.html \
html/man3/BIO_s_datagram.html \
html/man3/BIO_s_fd.html \
html/man3/BIO_s_file.html \
html/man3/BIO_s_mem.html \
html/man3/BIO_s_null.html \
html/man3/BIO_s_socket.html \
html/man3/BIO_set_callback.html \
html/man3/BIO_should_retry.html \
html/man3/BIO_socket_wait.html \
html/man3/BN_BLINDING_new.html \
html/man3/BN_CTX_new.html \
html/man3/BN_CTX_start.html \
html/man3/BN_add.html \
html/man3/BN_add_word.html \
html/man3/BN_bn2bin.html \
html/man3/BN_cmp.html \
html/man3/BN_copy.html \
html/man3/BN_generate_prime.html \
html/man3/BN_mod_exp_mont.html \
html/man3/BN_mod_inverse.html \
html/man3/BN_mod_mul_montgomery.html \
html/man3/BN_mod_mul_reciprocal.html \
html/man3/BN_new.html \
html/man3/BN_num_bytes.html \
html/man3/BN_rand.html \
html/man3/BN_security_bits.html \
html/man3/BN_set_bit.html \
html/man3/BN_swap.html \
html/man3/BN_zero.html \
html/man3/BUF_MEM_new.html \
html/man3/CMS_EncryptedData_decrypt.html \
html/man3/CMS_EncryptedData_encrypt.html \
html/man3/CMS_EnvelopedData_create.html \
html/man3/CMS_add0_cert.html \
html/man3/CMS_add1_recipient_cert.html \
html/man3/CMS_add1_signer.html \
html/man3/CMS_compress.html \
html/man3/CMS_data_create.html \
html/man3/CMS_decrypt.html \
html/man3/CMS_digest_create.html \
html/man3/CMS_encrypt.html \
html/man3/CMS_final.html \
html/man3/CMS_get0_RecipientInfos.html \
html/man3/CMS_get0_SignerInfos.html \
html/man3/CMS_get0_type.html \
html/man3/CMS_get1_ReceiptRequest.html \
html/man3/CMS_sign.html \
html/man3/CMS_sign_receipt.html \
html/man3/CMS_uncompress.html \
html/man3/CMS_verify.html \
html/man3/CMS_verify_receipt.html \
html/man3/CONF_modules_free.html \
html/man3/CONF_modules_load_file.html \
html/man3/CRYPTO_THREAD_run_once.html \
html/man3/CRYPTO_get_ex_new_index.html \
html/man3/CRYPTO_memcmp.html \
html/man3/CTLOG_STORE_get0_log_by_id.html \
html/man3/CTLOG_STORE_new.html \
html/man3/CTLOG_new.html \
html/man3/CT_POLICY_EVAL_CTX_new.html \
html/man3/DEFINE_STACK_OF.html \
html/man3/DES_random_key.html \
html/man3/DH_generate_key.html \
html/man3/DH_generate_parameters.html \
html/man3/DH_get0_pqg.html \
html/man3/DH_get_1024_160.html \
html/man3/DH_meth_new.html \
html/man3/DH_new.html \
html/man3/DH_new_by_nid.html \
html/man3/DH_set_method.html \
html/man3/DH_size.html \
html/man3/DSA_SIG_new.html \
html/man3/DSA_do_sign.html \
html/man3/DSA_dup_DH.html \
html/man3/DSA_generate_key.html \
html/man3/DSA_generate_parameters.html \
html/man3/DSA_get0_pqg.html \
html/man3/DSA_meth_new.html \
html/man3/DSA_new.html \
html/man3/DSA_set_method.html \
html/man3/DSA_sign.html \
html/man3/DSA_size.html \
html/man3/DTLS_get_data_mtu.html \
html/man3/DTLS_set_timer_cb.html \
html/man3/DTLSv1_listen.html \
html/man3/ECDSA_SIG_new.html \
html/man3/ECDSA_sign.html \
html/man3/ECPKParameters_print.html \
html/man3/EC_GFp_simple_method.html \
html/man3/EC_GROUP_copy.html \
html/man3/EC_GROUP_new.html \
html/man3/EC_KEY_get_enc_flags.html \
html/man3/EC_KEY_new.html \
html/man3/EC_POINT_add.html \
html/man3/EC_POINT_new.html \
html/man3/ENGINE_add.html \
html/man3/ERR_GET_LIB.html \
html/man3/ERR_clear_error.html \
html/man3/ERR_error_string.html \
html/man3/ERR_get_error.html \
html/man3/ERR_load_crypto_strings.html \
html/man3/ERR_load_strings.html \
html/man3/ERR_new.html \
html/man3/ERR_print_errors.html \
html/man3/ERR_put_error.html \
html/man3/ERR_remove_state.html \
html/man3/ERR_set_mark.html \
html/man3/EVP_ASYM_CIPHER_free.html \
html/man3/EVP_BytesToKey.html \
html/man3/EVP_CIPHER_CTX_get_cipher_data.html \
html/man3/EVP_CIPHER_CTX_get_original_iv.html \
html/man3/EVP_CIPHER_meth_new.html \
html/man3/EVP_DigestInit.html \
html/man3/EVP_DigestSignInit.html \
html/man3/EVP_DigestVerifyInit.html \
html/man3/EVP_EncodeInit.html \
html/man3/EVP_EncryptInit.html \
html/man3/EVP_KDF.html \
html/man3/EVP_KEM_free.html \
html/man3/EVP_KEYEXCH_free.html \
html/man3/EVP_KEYMGMT.html \
html/man3/EVP_MAC.html \
html/man3/EVP_MD_meth_new.html \
html/man3/EVP_OpenInit.html \
html/man3/EVP_PBE_CipherInit.html \
html/man3/EVP_PKEY2PKCS8.html \
html/man3/EVP_PKEY_ASN1_METHOD.html \
html/man3/EVP_PKEY_CTX_ctrl.html \
html/man3/EVP_PKEY_CTX_get0_libctx.html \
html/man3/EVP_PKEY_CTX_get0_pkey.html \
html/man3/EVP_PKEY_CTX_new.html \
html/man3/EVP_PKEY_CTX_set1_pbe_pass.html \
html/man3/EVP_PKEY_CTX_set_hkdf_md.html \
html/man3/EVP_PKEY_CTX_set_params.html \
html/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.html \
html/man3/EVP_PKEY_CTX_set_scrypt_N.html \
html/man3/EVP_PKEY_CTX_set_tls1_prf_md.html \
html/man3/EVP_PKEY_asn1_get_count.html \
html/man3/EVP_PKEY_check.html \
html/man3/EVP_PKEY_copy_parameters.html \
html/man3/EVP_PKEY_decapsulate.html \
html/man3/EVP_PKEY_decrypt.html \
html/man3/EVP_PKEY_derive.html \
html/man3/EVP_PKEY_digestsign_supports_digest.html \
html/man3/EVP_PKEY_encapsulate.html \
html/man3/EVP_PKEY_encrypt.html \
html/man3/EVP_PKEY_fromdata.html \
html/man3/EVP_PKEY_get_default_digest_nid.html \
html/man3/EVP_PKEY_get_field_type.html \
html/man3/EVP_PKEY_get_group_name.html \
html/man3/EVP_PKEY_get_size.html \
html/man3/EVP_PKEY_gettable_params.html \
html/man3/EVP_PKEY_is_a.html \
html/man3/EVP_PKEY_keygen.html \
html/man3/EVP_PKEY_meth_get_count.html \
html/man3/EVP_PKEY_meth_new.html \
html/man3/EVP_PKEY_new.html \
html/man3/EVP_PKEY_print_private.html \
html/man3/EVP_PKEY_set1_RSA.html \
html/man3/EVP_PKEY_set1_encoded_public_key.html \
html/man3/EVP_PKEY_set_type.html \
html/man3/EVP_PKEY_settable_params.html \
html/man3/EVP_PKEY_sign.html \
html/man3/EVP_PKEY_todata.html \
html/man3/EVP_PKEY_verify.html \
html/man3/EVP_PKEY_verify_recover.html \
html/man3/EVP_RAND.html \
html/man3/EVP_SIGNATURE.html \
html/man3/EVP_SealInit.html \
html/man3/EVP_SignInit.html \
html/man3/EVP_VerifyInit.html \
html/man3/EVP_aes_128_gcm.html \
html/man3/EVP_aria_128_gcm.html \
html/man3/EVP_bf_cbc.html \
html/man3/EVP_blake2b512.html \
html/man3/EVP_camellia_128_ecb.html \
html/man3/EVP_cast5_cbc.html \
html/man3/EVP_chacha20.html \
html/man3/EVP_des_cbc.html \
html/man3/EVP_desx_cbc.html \
html/man3/EVP_idea_cbc.html \
html/man3/EVP_md2.html \
html/man3/EVP_md4.html \
html/man3/EVP_md5.html \
html/man3/EVP_mdc2.html \
html/man3/EVP_rc2_cbc.html \
html/man3/EVP_rc4.html \
html/man3/EVP_rc5_32_12_16_cbc.html \
html/man3/EVP_ripemd160.html \
html/man3/EVP_seed_cbc.html \
html/man3/EVP_set_default_properties.html \
html/man3/EVP_sha1.html \
html/man3/EVP_sha224.html \
html/man3/EVP_sha3_224.html \
html/man3/EVP_sm3.html \
html/man3/EVP_sm4_cbc.html \
html/man3/EVP_whirlpool.html \
html/man3/HMAC.html \
html/man3/MD5.html \
html/man3/MDC2_Init.html \
html/man3/NCONF_new_ex.html \
html/man3/OBJ_nid2obj.html \
html/man3/OCSP_REQUEST_new.html \
html/man3/OCSP_cert_to_id.html \
html/man3/OCSP_request_add1_nonce.html \
html/man3/OCSP_resp_find_status.html \
html/man3/OCSP_response_status.html \
html/man3/OCSP_sendreq_new.html \
html/man3/OPENSSL_Applink.html \
html/man3/OPENSSL_FILE.html \
html/man3/OPENSSL_LH_COMPFUNC.html \
html/man3/OPENSSL_LH_stats.html \
html/man3/OPENSSL_config.html \
html/man3/OPENSSL_fork_prepare.html \
html/man3/OPENSSL_gmtime.html \
html/man3/OPENSSL_hexchar2int.html \
html/man3/OPENSSL_ia32cap.html \
html/man3/OPENSSL_init_crypto.html \
html/man3/OPENSSL_init_ssl.html \
html/man3/OPENSSL_instrument_bus.html \
html/man3/OPENSSL_load_builtin_modules.html \
html/man3/OPENSSL_malloc.html \
html/man3/OPENSSL_s390xcap.html \
html/man3/OPENSSL_secure_malloc.html \
html/man3/OPENSSL_strcasecmp.html \
html/man3/OSSL_ALGORITHM.html \
html/man3/OSSL_CALLBACK.html \
html/man3/OSSL_CMP_CTX_new.html \
html/man3/OSSL_CMP_HDR_get0_transactionID.html \
html/man3/OSSL_CMP_ITAV_set0.html \
html/man3/OSSL_CMP_MSG_get0_header.html \
html/man3/OSSL_CMP_MSG_http_perform.html \
html/man3/OSSL_CMP_SRV_CTX_new.html \
html/man3/OSSL_CMP_STATUSINFO_new.html \
html/man3/OSSL_CMP_exec_certreq.html \
html/man3/OSSL_CMP_log_open.html \
html/man3/OSSL_CMP_validate_msg.html \
html/man3/OSSL_CORE_MAKE_FUNC.html \
html/man3/OSSL_CRMF_MSG_get0_tmpl.html \
html/man3/OSSL_CRMF_MSG_set0_validity.html \
html/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.html \
html/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.html \
html/man3/OSSL_CRMF_pbmp_new.html \
html/man3/OSSL_DECODER.html \
html/man3/OSSL_DECODER_CTX.html \
html/man3/OSSL_DECODER_CTX_new_for_pkey.html \
html/man3/OSSL_DECODER_from_bio.html \
html/man3/OSSL_DISPATCH.html \
html/man3/OSSL_ENCODER.html \
html/man3/OSSL_ENCODER_CTX.html \
html/man3/OSSL_ENCODER_CTX_new_for_pkey.html \
html/man3/OSSL_ENCODER_to_bio.html \
html/man3/OSSL_ESS_check_signing_certs.html \
html/man3/OSSL_HTTP_REQ_CTX.html \
html/man3/OSSL_HTTP_parse_url.html \
html/man3/OSSL_HTTP_transfer.html \
html/man3/OSSL_ITEM.html \
html/man3/OSSL_LIB_CTX.html \
html/man3/OSSL_PARAM.html \
html/man3/OSSL_PARAM_BLD.html \
html/man3/OSSL_PARAM_allocate_from_text.html \
html/man3/OSSL_PARAM_dup.html \
html/man3/OSSL_PARAM_int.html \
html/man3/OSSL_PROVIDER.html \
html/man3/OSSL_SELF_TEST_new.html \
html/man3/OSSL_SELF_TEST_set_callback.html \
html/man3/OSSL_STORE_INFO.html \
html/man3/OSSL_STORE_LOADER.html \
html/man3/OSSL_STORE_SEARCH.html \
html/man3/OSSL_STORE_attach.html \
html/man3/OSSL_STORE_expect.html \
html/man3/OSSL_STORE_open.html \
html/man3/OSSL_trace_enabled.html \
html/man3/OSSL_trace_get_category_num.html \
html/man3/OSSL_trace_set_channel.html \
html/man3/OpenSSL_add_all_algorithms.html \
html/man3/OpenSSL_version.html \
html/man3/PEM_X509_INFO_read_bio_ex.html \
html/man3/PEM_bytes_read_bio.html \
html/man3/PEM_read.html \
html/man3/PEM_read_CMS.html \
html/man3/PEM_read_bio_PrivateKey.html \
html/man3/PEM_read_bio_ex.html \
html/man3/PEM_write_bio_CMS_stream.html \
html/man3/PEM_write_bio_PKCS7_stream.html \
html/man3/PKCS12_PBE_keyivgen.html \
html/man3/PKCS12_SAFEBAG_create_cert.html \
html/man3/PKCS12_SAFEBAG_get0_attrs.html \
html/man3/PKCS12_SAFEBAG_get1_cert.html \
html/man3/PKCS12_add1_attr_by_NID.html \
html/man3/PKCS12_add_CSPName_asc.html \
html/man3/PKCS12_add_cert.html \
html/man3/PKCS12_add_friendlyname_asc.html \
html/man3/PKCS12_add_localkeyid.html \
html/man3/PKCS12_add_safe.html \
html/man3/PKCS12_create.html \
html/man3/PKCS12_decrypt_skey.html \
html/man3/PKCS12_gen_mac.html \
html/man3/PKCS12_get_friendlyname.html \
html/man3/PKCS12_init.html \
html/man3/PKCS12_item_decrypt_d2i.html \
html/man3/PKCS12_key_gen_utf8_ex.html \
html/man3/PKCS12_newpass.html \
html/man3/PKCS12_pack_p7encdata.html \
html/man3/PKCS12_parse.html \
html/man3/PKCS5_PBE_keyivgen.html \
html/man3/PKCS5_PBKDF2_HMAC.html \
html/man3/PKCS7_decrypt.html \
html/man3/PKCS7_encrypt.html \
html/man3/PKCS7_get_octet_string.html \
html/man3/PKCS7_sign.html \
html/man3/PKCS7_sign_add_signer.html \
html/man3/PKCS7_type_is_other.html \
html/man3/PKCS7_verify.html \
html/man3/PKCS8_encrypt.html \
html/man3/PKCS8_pkey_add1_attr.html \
html/man3/RAND_add.html \
html/man3/RAND_bytes.html \
html/man3/RAND_cleanup.html \
html/man3/RAND_egd.html \
html/man3/RAND_get0_primary.html \
html/man3/RAND_load_file.html \
html/man3/RAND_set_DRBG_type.html \
html/man3/RAND_set_rand_method.html \
html/man3/RC4_set_key.html \
html/man3/RIPEMD160_Init.html \
html/man3/RSA_blinding_on.html \
html/man3/RSA_check_key.html \
html/man3/RSA_generate_key.html \
html/man3/RSA_get0_key.html \
html/man3/RSA_meth_new.html \
html/man3/RSA_new.html \
html/man3/RSA_padding_add_PKCS1_type_1.html \
html/man3/RSA_print.html \
html/man3/RSA_private_encrypt.html \
html/man3/RSA_public_encrypt.html \
html/man3/RSA_set_method.html \
html/man3/RSA_sign.html \
html/man3/RSA_sign_ASN1_OCTET_STRING.html \
html/man3/RSA_size.html \
html/man3/SCT_new.html \
html/man3/SCT_print.html \
html/man3/SCT_validate.html \
html/man3/SHA256_Init.html \
html/man3/SMIME_read_ASN1.html \
html/man3/SMIME_read_CMS.html \
html/man3/SMIME_read_PKCS7.html \
html/man3/SMIME_write_ASN1.html \
html/man3/SMIME_write_CMS.html \
html/man3/SMIME_write_PKCS7.html \
html/man3/SRP_Calc_B.html \
html/man3/SRP_VBASE_new.html \
html/man3/SRP_create_verifier.html \
html/man3/SRP_user_pwd_new.html \
html/man3/SSL_CIPHER_get_name.html \
html/man3/SSL_COMP_add_compression_method.html \
html/man3/SSL_CONF_CTX_new.html \
html/man3/SSL_CONF_CTX_set1_prefix.html \
html/man3/SSL_CONF_CTX_set_flags.html \
html/man3/SSL_CONF_CTX_set_ssl_ctx.html \
html/man3/SSL_CONF_cmd.html \
html/man3/SSL_CONF_cmd_argv.html \
html/man3/SSL_CTX_add1_chain_cert.html \
html/man3/SSL_CTX_add_extra_chain_cert.html \
html/man3/SSL_CTX_add_session.html \
html/man3/SSL_CTX_config.html \
html/man3/SSL_CTX_ctrl.html \
html/man3/SSL_CTX_dane_enable.html \
html/man3/SSL_CTX_flush_sessions.html \
html/man3/SSL_CTX_free.html \
html/man3/SSL_CTX_get0_param.html \
html/man3/SSL_CTX_get_verify_mode.html \
html/man3/SSL_CTX_has_client_custom_ext.html \
html/man3/SSL_CTX_load_verify_locations.html \
html/man3/SSL_CTX_new.html \
html/man3/SSL_CTX_sess_number.html \
html/man3/SSL_CTX_sess_set_cache_size.html \
html/man3/SSL_CTX_sess_set_get_cb.html \
html/man3/SSL_CTX_sessions.html \
html/man3/SSL_CTX_set0_CA_list.html \
html/man3/SSL_CTX_set1_curves.html \
html/man3/SSL_CTX_set1_sigalgs.html \
html/man3/SSL_CTX_set1_verify_cert_store.html \
html/man3/SSL_CTX_set_alpn_select_cb.html \
html/man3/SSL_CTX_set_cert_cb.html \
html/man3/SSL_CTX_set_cert_store.html \
html/man3/SSL_CTX_set_cert_verify_callback.html \
html/man3/SSL_CTX_set_cipher_list.html \
html/man3/SSL_CTX_set_client_cert_cb.html \
html/man3/SSL_CTX_set_client_hello_cb.html \
html/man3/SSL_CTX_set_ct_validation_callback.html \
html/man3/SSL_CTX_set_ctlog_list_file.html \
html/man3/SSL_CTX_set_default_passwd_cb.html \
html/man3/SSL_CTX_set_generate_session_id.html \
html/man3/SSL_CTX_set_info_callback.html \
html/man3/SSL_CTX_set_keylog_callback.html \
html/man3/SSL_CTX_set_max_cert_list.html \
html/man3/SSL_CTX_set_min_proto_version.html \
html/man3/SSL_CTX_set_mode.html \
html/man3/SSL_CTX_set_msg_callback.html \
html/man3/SSL_CTX_set_num_tickets.html \
html/man3/SSL_CTX_set_options.html \
html/man3/SSL_CTX_set_psk_client_callback.html \
html/man3/SSL_CTX_set_quiet_shutdown.html \
html/man3/SSL_CTX_set_read_ahead.html \
html/man3/SSL_CTX_set_record_padding_callback.html \
html/man3/SSL_CTX_set_security_level.html \
html/man3/SSL_CTX_set_session_cache_mode.html \
html/man3/SSL_CTX_set_session_id_context.html \
html/man3/SSL_CTX_set_session_ticket_cb.html \
html/man3/SSL_CTX_set_split_send_fragment.html \
html/man3/SSL_CTX_set_srp_password.html \
html/man3/SSL_CTX_set_ssl_version.html \
html/man3/SSL_CTX_set_stateless_cookie_generate_cb.html \
html/man3/SSL_CTX_set_timeout.html \
html/man3/SSL_CTX_set_tlsext_servername_callback.html \
html/man3/SSL_CTX_set_tlsext_status_cb.html \
html/man3/SSL_CTX_set_tlsext_ticket_key_cb.html \
html/man3/SSL_CTX_set_tlsext_use_srtp.html \
html/man3/SSL_CTX_set_tmp_dh_callback.html \
html/man3/SSL_CTX_set_tmp_ecdh.html \
html/man3/SSL_CTX_set_verify.html \
html/man3/SSL_CTX_use_certificate.html \
html/man3/SSL_CTX_use_psk_identity_hint.html \
html/man3/SSL_CTX_use_serverinfo.html \
html/man3/SSL_SESSION_free.html \
html/man3/SSL_SESSION_get0_cipher.html \
html/man3/SSL_SESSION_get0_hostname.html \
html/man3/SSL_SESSION_get0_id_context.html \
html/man3/SSL_SESSION_get0_peer.html \
html/man3/SSL_SESSION_get_compress_id.html \
html/man3/SSL_SESSION_get_protocol_version.html \
html/man3/SSL_SESSION_get_time.html \
html/man3/SSL_SESSION_has_ticket.html \
html/man3/SSL_SESSION_is_resumable.html \
html/man3/SSL_SESSION_print.html \
html/man3/SSL_SESSION_set1_id.html \
html/man3/SSL_accept.html \
html/man3/SSL_alert_type_string.html \
html/man3/SSL_alloc_buffers.html \
html/man3/SSL_check_chain.html \
html/man3/SSL_clear.html \
html/man3/SSL_connect.html \
html/man3/SSL_do_handshake.html \
html/man3/SSL_export_keying_material.html \
html/man3/SSL_extension_supported.html \
html/man3/SSL_free.html \
html/man3/SSL_get0_peer_scts.html \
html/man3/SSL_get_SSL_CTX.html \
html/man3/SSL_get_all_async_fds.html \
html/man3/SSL_get_certificate.html \
html/man3/SSL_get_ciphers.html \
html/man3/SSL_get_client_random.html \
html/man3/SSL_get_current_cipher.html \
html/man3/SSL_get_default_timeout.html \
html/man3/SSL_get_error.html \
html/man3/SSL_get_extms_support.html \
html/man3/SSL_get_fd.html \
html/man3/SSL_get_peer_cert_chain.html \
html/man3/SSL_get_peer_certificate.html \
html/man3/SSL_get_peer_signature_nid.html \
html/man3/SSL_get_peer_tmp_key.html \
html/man3/SSL_get_psk_identity.html \
html/man3/SSL_get_rbio.html \
html/man3/SSL_get_session.html \
html/man3/SSL_get_shared_sigalgs.html \
html/man3/SSL_get_verify_result.html \
html/man3/SSL_get_version.html \
html/man3/SSL_group_to_name.html \
html/man3/SSL_in_init.html \
html/man3/SSL_key_update.html \
html/man3/SSL_library_init.html \
html/man3/SSL_load_client_CA_file.html \
html/man3/SSL_new.html \
html/man3/SSL_pending.html \
html/man3/SSL_read.html \
html/man3/SSL_read_early_data.html \
html/man3/SSL_rstate_string.html \
html/man3/SSL_session_reused.html \
html/man3/SSL_set1_host.html \
html/man3/SSL_set_async_callback.html \
html/man3/SSL_set_bio.html \
html/man3/SSL_set_connect_state.html \
html/man3/SSL_set_fd.html \
html/man3/SSL_set_retry_verify.html \
html/man3/SSL_set_session.html \
html/man3/SSL_set_shutdown.html \
html/man3/SSL_set_verify_result.html \
html/man3/SSL_shutdown.html \
html/man3/SSL_state_string.html \
html/man3/SSL_want.html \
html/man3/SSL_write.html \
html/man3/TS_RESP_CTX_new.html \
html/man3/TS_VERIFY_CTX_set_certs.html \
html/man3/UI_STRING.html \
html/man3/UI_UTIL_read_pw.html \
html/man3/UI_create_method.html \
html/man3/UI_new.html \
html/man3/X509V3_get_d2i.html \
html/man3/X509V3_set_ctx.html \
html/man3/X509_ALGOR_dup.html \
html/man3/X509_CRL_get0_by_serial.html \
html/man3/X509_EXTENSION_set_object.html \
html/man3/X509_LOOKUP.html \
html/man3/X509_LOOKUP_hash_dir.html \
html/man3/X509_LOOKUP_meth_new.html \
html/man3/X509_NAME_ENTRY_get_object.html \
html/man3/X509_NAME_add_entry_by_txt.html \
html/man3/X509_NAME_get0_der.html \
html/man3/X509_NAME_get_index_by_NID.html \
html/man3/X509_NAME_print_ex.html \
html/man3/X509_PUBKEY_new.html \
html/man3/X509_SIG_get0.html \
html/man3/X509_STORE_CTX_get_error.html \
html/man3/X509_STORE_CTX_new.html \
html/man3/X509_STORE_CTX_set_verify_cb.html \
html/man3/X509_STORE_add_cert.html \
html/man3/X509_STORE_get0_param.html \
html/man3/X509_STORE_new.html \
html/man3/X509_STORE_set_verify_cb_func.html \
html/man3/X509_VERIFY_PARAM_set_flags.html \
html/man3/X509_add_cert.html \
html/man3/X509_check_ca.html \
html/man3/X509_check_host.html \
html/man3/X509_check_issued.html \
html/man3/X509_check_private_key.html \
html/man3/X509_check_purpose.html \
html/man3/X509_cmp.html \
html/man3/X509_cmp_time.html \
html/man3/X509_digest.html \
html/man3/X509_dup.html \
html/man3/X509_get0_distinguishing_id.html \
html/man3/X509_get0_notBefore.html \
html/man3/X509_get0_signature.html \
html/man3/X509_get0_uids.html \
html/man3/X509_get_extension_flags.html \
html/man3/X509_get_pubkey.html \
html/man3/X509_get_serialNumber.html \
html/man3/X509_get_subject_name.html \
html/man3/X509_get_version.html \
html/man3/X509_load_http.html \
html/man3/X509_new.html \
html/man3/X509_sign.html \
html/man3/X509_verify.html \
html/man3/X509_verify_cert.html \
html/man3/X509v3_get_ext_by_NID.html \
html/man3/b2i_PVK_bio_ex.html \
html/man3/d2i_PKCS8PrivateKey_bio.html \
html/man3/d2i_PrivateKey.html \
html/man3/d2i_RSAPrivateKey.html \
html/man3/d2i_SSL_SESSION.html \
html/man3/d2i_X509.html \
html/man3/i2d_CMS_bio_stream.html \
html/man3/i2d_PKCS7_bio_stream.html \
html/man3/i2d_re_X509_tbs.html \
html/man3/o2i_SCT_LIST.html \
html/man3/s2i_ASN1_IA5STRING.html
MANDOCS[man3]=man/man3/ADMISSIONS.3 \
man/man3/ASN1_EXTERN_FUNCS.3 \
man/man3/ASN1_INTEGER_get_int64.3 \
man/man3/ASN1_INTEGER_new.3 \
man/man3/ASN1_ITEM_lookup.3 \
man/man3/ASN1_OBJECT_new.3 \
man/man3/ASN1_STRING_TABLE_add.3 \
man/man3/ASN1_STRING_length.3 \
man/man3/ASN1_STRING_new.3 \
man/man3/ASN1_STRING_print_ex.3 \
man/man3/ASN1_TIME_set.3 \
man/man3/ASN1_TYPE_get.3 \
man/man3/ASN1_aux_cb.3 \
man/man3/ASN1_generate_nconf.3 \
man/man3/ASN1_item_d2i_bio.3 \
man/man3/ASN1_item_new.3 \
man/man3/ASN1_item_sign.3 \
man/man3/ASYNC_WAIT_CTX_new.3 \
man/man3/ASYNC_start_job.3 \
man/man3/BF_encrypt.3 \
man/man3/BIO_ADDR.3 \
man/man3/BIO_ADDRINFO.3 \
man/man3/BIO_connect.3 \
man/man3/BIO_ctrl.3 \
man/man3/BIO_f_base64.3 \
man/man3/BIO_f_buffer.3 \
man/man3/BIO_f_cipher.3 \
man/man3/BIO_f_md.3 \
man/man3/BIO_f_null.3 \
man/man3/BIO_f_prefix.3 \
man/man3/BIO_f_readbuffer.3 \
man/man3/BIO_f_ssl.3 \
man/man3/BIO_find_type.3 \
man/man3/BIO_get_data.3 \
man/man3/BIO_get_ex_new_index.3 \
man/man3/BIO_meth_new.3 \
man/man3/BIO_new.3 \
man/man3/BIO_new_CMS.3 \
man/man3/BIO_parse_hostserv.3 \
man/man3/BIO_printf.3 \
man/man3/BIO_push.3 \
man/man3/BIO_read.3 \
man/man3/BIO_s_accept.3 \
man/man3/BIO_s_bio.3 \
man/man3/BIO_s_connect.3 \
man/man3/BIO_s_core.3 \
man/man3/BIO_s_datagram.3 \
man/man3/BIO_s_fd.3 \
man/man3/BIO_s_file.3 \
man/man3/BIO_s_mem.3 \
man/man3/BIO_s_null.3 \
man/man3/BIO_s_socket.3 \
man/man3/BIO_set_callback.3 \
man/man3/BIO_should_retry.3 \
man/man3/BIO_socket_wait.3 \
man/man3/BN_BLINDING_new.3 \
man/man3/BN_CTX_new.3 \
man/man3/BN_CTX_start.3 \
man/man3/BN_add.3 \
man/man3/BN_add_word.3 \
man/man3/BN_bn2bin.3 \
man/man3/BN_cmp.3 \
man/man3/BN_copy.3 \
man/man3/BN_generate_prime.3 \
man/man3/BN_mod_exp_mont.3 \
man/man3/BN_mod_inverse.3 \
man/man3/BN_mod_mul_montgomery.3 \
man/man3/BN_mod_mul_reciprocal.3 \
man/man3/BN_new.3 \
man/man3/BN_num_bytes.3 \
man/man3/BN_rand.3 \
man/man3/BN_security_bits.3 \
man/man3/BN_set_bit.3 \
man/man3/BN_swap.3 \
man/man3/BN_zero.3 \
man/man3/BUF_MEM_new.3 \
man/man3/CMS_EncryptedData_decrypt.3 \
man/man3/CMS_EncryptedData_encrypt.3 \
man/man3/CMS_EnvelopedData_create.3 \
man/man3/CMS_add0_cert.3 \
man/man3/CMS_add1_recipient_cert.3 \
man/man3/CMS_add1_signer.3 \
man/man3/CMS_compress.3 \
man/man3/CMS_data_create.3 \
man/man3/CMS_decrypt.3 \
man/man3/CMS_digest_create.3 \
man/man3/CMS_encrypt.3 \
man/man3/CMS_final.3 \
man/man3/CMS_get0_RecipientInfos.3 \
man/man3/CMS_get0_SignerInfos.3 \
man/man3/CMS_get0_type.3 \
man/man3/CMS_get1_ReceiptRequest.3 \
man/man3/CMS_sign.3 \
man/man3/CMS_sign_receipt.3 \
man/man3/CMS_uncompress.3 \
man/man3/CMS_verify.3 \
man/man3/CMS_verify_receipt.3 \
man/man3/CONF_modules_free.3 \
man/man3/CONF_modules_load_file.3 \
man/man3/CRYPTO_THREAD_run_once.3 \
man/man3/CRYPTO_get_ex_new_index.3 \
man/man3/CRYPTO_memcmp.3 \
man/man3/CTLOG_STORE_get0_log_by_id.3 \
man/man3/CTLOG_STORE_new.3 \
man/man3/CTLOG_new.3 \
man/man3/CT_POLICY_EVAL_CTX_new.3 \
man/man3/DEFINE_STACK_OF.3 \
man/man3/DES_random_key.3 \
man/man3/DH_generate_key.3 \
man/man3/DH_generate_parameters.3 \
man/man3/DH_get0_pqg.3 \
man/man3/DH_get_1024_160.3 \
man/man3/DH_meth_new.3 \
man/man3/DH_new.3 \
man/man3/DH_new_by_nid.3 \
man/man3/DH_set_method.3 \
man/man3/DH_size.3 \
man/man3/DSA_SIG_new.3 \
man/man3/DSA_do_sign.3 \
man/man3/DSA_dup_DH.3 \
man/man3/DSA_generate_key.3 \
man/man3/DSA_generate_parameters.3 \
man/man3/DSA_get0_pqg.3 \
man/man3/DSA_meth_new.3 \
man/man3/DSA_new.3 \
man/man3/DSA_set_method.3 \
man/man3/DSA_sign.3 \
man/man3/DSA_size.3 \
man/man3/DTLS_get_data_mtu.3 \
man/man3/DTLS_set_timer_cb.3 \
man/man3/DTLSv1_listen.3 \
man/man3/ECDSA_SIG_new.3 \
man/man3/ECDSA_sign.3 \
man/man3/ECPKParameters_print.3 \
man/man3/EC_GFp_simple_method.3 \
man/man3/EC_GROUP_copy.3 \
man/man3/EC_GROUP_new.3 \
man/man3/EC_KEY_get_enc_flags.3 \
man/man3/EC_KEY_new.3 \
man/man3/EC_POINT_add.3 \
man/man3/EC_POINT_new.3 \
man/man3/ENGINE_add.3 \
man/man3/ERR_GET_LIB.3 \
man/man3/ERR_clear_error.3 \
man/man3/ERR_error_string.3 \
man/man3/ERR_get_error.3 \
man/man3/ERR_load_crypto_strings.3 \
man/man3/ERR_load_strings.3 \
man/man3/ERR_new.3 \
man/man3/ERR_print_errors.3 \
man/man3/ERR_put_error.3 \
man/man3/ERR_remove_state.3 \
man/man3/ERR_set_mark.3 \
man/man3/EVP_ASYM_CIPHER_free.3 \
man/man3/EVP_BytesToKey.3 \
man/man3/EVP_CIPHER_CTX_get_cipher_data.3 \
man/man3/EVP_CIPHER_CTX_get_original_iv.3 \
man/man3/EVP_CIPHER_meth_new.3 \
man/man3/EVP_DigestInit.3 \
man/man3/EVP_DigestSignInit.3 \
man/man3/EVP_DigestVerifyInit.3 \
man/man3/EVP_EncodeInit.3 \
man/man3/EVP_EncryptInit.3 \
man/man3/EVP_KDF.3 \
man/man3/EVP_KEM_free.3 \
man/man3/EVP_KEYEXCH_free.3 \
man/man3/EVP_KEYMGMT.3 \
man/man3/EVP_MAC.3 \
man/man3/EVP_MD_meth_new.3 \
man/man3/EVP_OpenInit.3 \
man/man3/EVP_PBE_CipherInit.3 \
man/man3/EVP_PKEY2PKCS8.3 \
man/man3/EVP_PKEY_ASN1_METHOD.3 \
man/man3/EVP_PKEY_CTX_ctrl.3 \
man/man3/EVP_PKEY_CTX_get0_libctx.3 \
man/man3/EVP_PKEY_CTX_get0_pkey.3 \
man/man3/EVP_PKEY_CTX_new.3 \
man/man3/EVP_PKEY_CTX_set1_pbe_pass.3 \
man/man3/EVP_PKEY_CTX_set_hkdf_md.3 \
man/man3/EVP_PKEY_CTX_set_params.3 \
man/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.3 \
man/man3/EVP_PKEY_CTX_set_scrypt_N.3 \
man/man3/EVP_PKEY_CTX_set_tls1_prf_md.3 \
man/man3/EVP_PKEY_asn1_get_count.3 \
man/man3/EVP_PKEY_check.3 \
man/man3/EVP_PKEY_copy_parameters.3 \
man/man3/EVP_PKEY_decapsulate.3 \
man/man3/EVP_PKEY_decrypt.3 \
man/man3/EVP_PKEY_derive.3 \
man/man3/EVP_PKEY_digestsign_supports_digest.3 \
man/man3/EVP_PKEY_encapsulate.3 \
man/man3/EVP_PKEY_encrypt.3 \
man/man3/EVP_PKEY_fromdata.3 \
man/man3/EVP_PKEY_get_default_digest_nid.3 \
man/man3/EVP_PKEY_get_field_type.3 \
man/man3/EVP_PKEY_get_group_name.3 \
man/man3/EVP_PKEY_get_size.3 \
man/man3/EVP_PKEY_gettable_params.3 \
man/man3/EVP_PKEY_is_a.3 \
man/man3/EVP_PKEY_keygen.3 \
man/man3/EVP_PKEY_meth_get_count.3 \
man/man3/EVP_PKEY_meth_new.3 \
man/man3/EVP_PKEY_new.3 \
man/man3/EVP_PKEY_print_private.3 \
man/man3/EVP_PKEY_set1_RSA.3 \
man/man3/EVP_PKEY_set1_encoded_public_key.3 \
man/man3/EVP_PKEY_set_type.3 \
man/man3/EVP_PKEY_settable_params.3 \
man/man3/EVP_PKEY_sign.3 \
man/man3/EVP_PKEY_todata.3 \
man/man3/EVP_PKEY_verify.3 \
man/man3/EVP_PKEY_verify_recover.3 \
man/man3/EVP_RAND.3 \
man/man3/EVP_SIGNATURE.3 \
man/man3/EVP_SealInit.3 \
man/man3/EVP_SignInit.3 \
man/man3/EVP_VerifyInit.3 \
man/man3/EVP_aes_128_gcm.3 \
man/man3/EVP_aria_128_gcm.3 \
man/man3/EVP_bf_cbc.3 \
man/man3/EVP_blake2b512.3 \
man/man3/EVP_camellia_128_ecb.3 \
man/man3/EVP_cast5_cbc.3 \
man/man3/EVP_chacha20.3 \
man/man3/EVP_des_cbc.3 \
man/man3/EVP_desx_cbc.3 \
man/man3/EVP_idea_cbc.3 \
man/man3/EVP_md2.3 \
man/man3/EVP_md4.3 \
man/man3/EVP_md5.3 \
man/man3/EVP_mdc2.3 \
man/man3/EVP_rc2_cbc.3 \
man/man3/EVP_rc4.3 \
man/man3/EVP_rc5_32_12_16_cbc.3 \
man/man3/EVP_ripemd160.3 \
man/man3/EVP_seed_cbc.3 \
man/man3/EVP_set_default_properties.3 \
man/man3/EVP_sha1.3 \
man/man3/EVP_sha224.3 \
man/man3/EVP_sha3_224.3 \
man/man3/EVP_sm3.3 \
man/man3/EVP_sm4_cbc.3 \
man/man3/EVP_whirlpool.3 \
man/man3/HMAC.3 \
man/man3/MD5.3 \
man/man3/MDC2_Init.3 \
man/man3/NCONF_new_ex.3 \
man/man3/OBJ_nid2obj.3 \
man/man3/OCSP_REQUEST_new.3 \
man/man3/OCSP_cert_to_id.3 \
man/man3/OCSP_request_add1_nonce.3 \
man/man3/OCSP_resp_find_status.3 \
man/man3/OCSP_response_status.3 \
man/man3/OCSP_sendreq_new.3 \
man/man3/OPENSSL_Applink.3 \
man/man3/OPENSSL_FILE.3 \
man/man3/OPENSSL_LH_COMPFUNC.3 \
man/man3/OPENSSL_LH_stats.3 \
man/man3/OPENSSL_config.3 \
man/man3/OPENSSL_fork_prepare.3 \
man/man3/OPENSSL_gmtime.3 \
man/man3/OPENSSL_hexchar2int.3 \
man/man3/OPENSSL_ia32cap.3 \
man/man3/OPENSSL_init_crypto.3 \
man/man3/OPENSSL_init_ssl.3 \
man/man3/OPENSSL_instrument_bus.3 \
man/man3/OPENSSL_load_builtin_modules.3 \
man/man3/OPENSSL_malloc.3 \
man/man3/OPENSSL_s390xcap.3 \
man/man3/OPENSSL_secure_malloc.3 \
man/man3/OPENSSL_strcasecmp.3 \
man/man3/OSSL_ALGORITHM.3 \
man/man3/OSSL_CALLBACK.3 \
man/man3/OSSL_CMP_CTX_new.3 \
man/man3/OSSL_CMP_HDR_get0_transactionID.3 \
man/man3/OSSL_CMP_ITAV_set0.3 \
man/man3/OSSL_CMP_MSG_get0_header.3 \
man/man3/OSSL_CMP_MSG_http_perform.3 \
man/man3/OSSL_CMP_SRV_CTX_new.3 \
man/man3/OSSL_CMP_STATUSINFO_new.3 \
man/man3/OSSL_CMP_exec_certreq.3 \
man/man3/OSSL_CMP_log_open.3 \
man/man3/OSSL_CMP_validate_msg.3 \
man/man3/OSSL_CORE_MAKE_FUNC.3 \
man/man3/OSSL_CRMF_MSG_get0_tmpl.3 \
man/man3/OSSL_CRMF_MSG_set0_validity.3 \
man/man3/OSSL_CRMF_MSG_set1_regCtrl_regToken.3 \
man/man3/OSSL_CRMF_MSG_set1_regInfo_certReq.3 \
man/man3/OSSL_CRMF_pbmp_new.3 \
man/man3/OSSL_DECODER.3 \
man/man3/OSSL_DECODER_CTX.3 \
man/man3/OSSL_DECODER_CTX_new_for_pkey.3 \
man/man3/OSSL_DECODER_from_bio.3 \
man/man3/OSSL_DISPATCH.3 \
man/man3/OSSL_ENCODER.3 \
man/man3/OSSL_ENCODER_CTX.3 \
man/man3/OSSL_ENCODER_CTX_new_for_pkey.3 \
man/man3/OSSL_ENCODER_to_bio.3 \
man/man3/OSSL_ESS_check_signing_certs.3 \
man/man3/OSSL_HTTP_REQ_CTX.3 \
man/man3/OSSL_HTTP_parse_url.3 \
man/man3/OSSL_HTTP_transfer.3 \
man/man3/OSSL_ITEM.3 \
man/man3/OSSL_LIB_CTX.3 \
man/man3/OSSL_PARAM.3 \
man/man3/OSSL_PARAM_BLD.3 \
man/man3/OSSL_PARAM_allocate_from_text.3 \
man/man3/OSSL_PARAM_dup.3 \
man/man3/OSSL_PARAM_int.3 \
man/man3/OSSL_PROVIDER.3 \
man/man3/OSSL_SELF_TEST_new.3 \
man/man3/OSSL_SELF_TEST_set_callback.3 \
man/man3/OSSL_STORE_INFO.3 \
man/man3/OSSL_STORE_LOADER.3 \
man/man3/OSSL_STORE_SEARCH.3 \
man/man3/OSSL_STORE_attach.3 \
man/man3/OSSL_STORE_expect.3 \
man/man3/OSSL_STORE_open.3 \
man/man3/OSSL_trace_enabled.3 \
man/man3/OSSL_trace_get_category_num.3 \
man/man3/OSSL_trace_set_channel.3 \
man/man3/OpenSSL_add_all_algorithms.3 \
man/man3/OpenSSL_version.3 \
man/man3/PEM_X509_INFO_read_bio_ex.3 \
man/man3/PEM_bytes_read_bio.3 \
man/man3/PEM_read.3 \
man/man3/PEM_read_CMS.3 \
man/man3/PEM_read_bio_PrivateKey.3 \
man/man3/PEM_read_bio_ex.3 \
man/man3/PEM_write_bio_CMS_stream.3 \
man/man3/PEM_write_bio_PKCS7_stream.3 \
man/man3/PKCS12_PBE_keyivgen.3 \
man/man3/PKCS12_SAFEBAG_create_cert.3 \
man/man3/PKCS12_SAFEBAG_get0_attrs.3 \
man/man3/PKCS12_SAFEBAG_get1_cert.3 \
man/man3/PKCS12_add1_attr_by_NID.3 \
man/man3/PKCS12_add_CSPName_asc.3 \
man/man3/PKCS12_add_cert.3 \
man/man3/PKCS12_add_friendlyname_asc.3 \
man/man3/PKCS12_add_localkeyid.3 \
man/man3/PKCS12_add_safe.3 \
man/man3/PKCS12_create.3 \
man/man3/PKCS12_decrypt_skey.3 \
man/man3/PKCS12_gen_mac.3 \
man/man3/PKCS12_get_friendlyname.3 \
man/man3/PKCS12_init.3 \
man/man3/PKCS12_item_decrypt_d2i.3 \
man/man3/PKCS12_key_gen_utf8_ex.3 \
man/man3/PKCS12_newpass.3 \
man/man3/PKCS12_pack_p7encdata.3 \
man/man3/PKCS12_parse.3 \
man/man3/PKCS5_PBE_keyivgen.3 \
man/man3/PKCS5_PBKDF2_HMAC.3 \
man/man3/PKCS7_decrypt.3 \
man/man3/PKCS7_encrypt.3 \
man/man3/PKCS7_get_octet_string.3 \
man/man3/PKCS7_sign.3 \
man/man3/PKCS7_sign_add_signer.3 \
man/man3/PKCS7_type_is_other.3 \
man/man3/PKCS7_verify.3 \
man/man3/PKCS8_encrypt.3 \
man/man3/PKCS8_pkey_add1_attr.3 \
man/man3/RAND_add.3 \
man/man3/RAND_bytes.3 \
man/man3/RAND_cleanup.3 \
man/man3/RAND_egd.3 \
man/man3/RAND_get0_primary.3 \
man/man3/RAND_load_file.3 \
man/man3/RAND_set_DRBG_type.3 \
man/man3/RAND_set_rand_method.3 \
man/man3/RC4_set_key.3 \
man/man3/RIPEMD160_Init.3 \
man/man3/RSA_blinding_on.3 \
man/man3/RSA_check_key.3 \
man/man3/RSA_generate_key.3 \
man/man3/RSA_get0_key.3 \
man/man3/RSA_meth_new.3 \
man/man3/RSA_new.3 \
man/man3/RSA_padding_add_PKCS1_type_1.3 \
man/man3/RSA_print.3 \
man/man3/RSA_private_encrypt.3 \
man/man3/RSA_public_encrypt.3 \
man/man3/RSA_set_method.3 \
man/man3/RSA_sign.3 \
man/man3/RSA_sign_ASN1_OCTET_STRING.3 \
man/man3/RSA_size.3 \
man/man3/SCT_new.3 \
man/man3/SCT_print.3 \
man/man3/SCT_validate.3 \
man/man3/SHA256_Init.3 \
man/man3/SMIME_read_ASN1.3 \
man/man3/SMIME_read_CMS.3 \
man/man3/SMIME_read_PKCS7.3 \
man/man3/SMIME_write_ASN1.3 \
man/man3/SMIME_write_CMS.3 \
man/man3/SMIME_write_PKCS7.3 \
man/man3/SRP_Calc_B.3 \
man/man3/SRP_VBASE_new.3 \
man/man3/SRP_create_verifier.3 \
man/man3/SRP_user_pwd_new.3 \
man/man3/SSL_CIPHER_get_name.3 \
man/man3/SSL_COMP_add_compression_method.3 \
man/man3/SSL_CONF_CTX_new.3 \
man/man3/SSL_CONF_CTX_set1_prefix.3 \
man/man3/SSL_CONF_CTX_set_flags.3 \
man/man3/SSL_CONF_CTX_set_ssl_ctx.3 \
man/man3/SSL_CONF_cmd.3 \
man/man3/SSL_CONF_cmd_argv.3 \
man/man3/SSL_CTX_add1_chain_cert.3 \
man/man3/SSL_CTX_add_extra_chain_cert.3 \
man/man3/SSL_CTX_add_session.3 \
man/man3/SSL_CTX_config.3 \
man/man3/SSL_CTX_ctrl.3 \
man/man3/SSL_CTX_dane_enable.3 \
man/man3/SSL_CTX_flush_sessions.3 \
man/man3/SSL_CTX_free.3 \
man/man3/SSL_CTX_get0_param.3 \
man/man3/SSL_CTX_get_verify_mode.3 \
man/man3/SSL_CTX_has_client_custom_ext.3 \
man/man3/SSL_CTX_load_verify_locations.3 \
man/man3/SSL_CTX_new.3 \
man/man3/SSL_CTX_sess_number.3 \
man/man3/SSL_CTX_sess_set_cache_size.3 \
man/man3/SSL_CTX_sess_set_get_cb.3 \
man/man3/SSL_CTX_sessions.3 \
man/man3/SSL_CTX_set0_CA_list.3 \
man/man3/SSL_CTX_set1_curves.3 \
man/man3/SSL_CTX_set1_sigalgs.3 \
man/man3/SSL_CTX_set1_verify_cert_store.3 \
man/man3/SSL_CTX_set_alpn_select_cb.3 \
man/man3/SSL_CTX_set_cert_cb.3 \
man/man3/SSL_CTX_set_cert_store.3 \
man/man3/SSL_CTX_set_cert_verify_callback.3 \
man/man3/SSL_CTX_set_cipher_list.3 \
man/man3/SSL_CTX_set_client_cert_cb.3 \
man/man3/SSL_CTX_set_client_hello_cb.3 \
man/man3/SSL_CTX_set_ct_validation_callback.3 \
man/man3/SSL_CTX_set_ctlog_list_file.3 \
man/man3/SSL_CTX_set_default_passwd_cb.3 \
man/man3/SSL_CTX_set_generate_session_id.3 \
man/man3/SSL_CTX_set_info_callback.3 \
man/man3/SSL_CTX_set_keylog_callback.3 \
man/man3/SSL_CTX_set_max_cert_list.3 \
man/man3/SSL_CTX_set_min_proto_version.3 \
man/man3/SSL_CTX_set_mode.3 \
man/man3/SSL_CTX_set_msg_callback.3 \
man/man3/SSL_CTX_set_num_tickets.3 \
man/man3/SSL_CTX_set_options.3 \
man/man3/SSL_CTX_set_psk_client_callback.3 \
man/man3/SSL_CTX_set_quiet_shutdown.3 \
man/man3/SSL_CTX_set_read_ahead.3 \
man/man3/SSL_CTX_set_record_padding_callback.3 \
man/man3/SSL_CTX_set_security_level.3 \
man/man3/SSL_CTX_set_session_cache_mode.3 \
man/man3/SSL_CTX_set_session_id_context.3 \
man/man3/SSL_CTX_set_session_ticket_cb.3 \
man/man3/SSL_CTX_set_split_send_fragment.3 \
man/man3/SSL_CTX_set_srp_password.3 \
man/man3/SSL_CTX_set_ssl_version.3 \
man/man3/SSL_CTX_set_stateless_cookie_generate_cb.3 \
man/man3/SSL_CTX_set_timeout.3 \
man/man3/SSL_CTX_set_tlsext_servername_callback.3 \
man/man3/SSL_CTX_set_tlsext_status_cb.3 \
man/man3/SSL_CTX_set_tlsext_ticket_key_cb.3 \
man/man3/SSL_CTX_set_tlsext_use_srtp.3 \
man/man3/SSL_CTX_set_tmp_dh_callback.3 \
man/man3/SSL_CTX_set_tmp_ecdh.3 \
man/man3/SSL_CTX_set_verify.3 \
man/man3/SSL_CTX_use_certificate.3 \
man/man3/SSL_CTX_use_psk_identity_hint.3 \
man/man3/SSL_CTX_use_serverinfo.3 \
man/man3/SSL_SESSION_free.3 \
man/man3/SSL_SESSION_get0_cipher.3 \
man/man3/SSL_SESSION_get0_hostname.3 \
man/man3/SSL_SESSION_get0_id_context.3 \
man/man3/SSL_SESSION_get0_peer.3 \
man/man3/SSL_SESSION_get_compress_id.3 \
man/man3/SSL_SESSION_get_protocol_version.3 \
man/man3/SSL_SESSION_get_time.3 \
man/man3/SSL_SESSION_has_ticket.3 \
man/man3/SSL_SESSION_is_resumable.3 \
man/man3/SSL_SESSION_print.3 \
man/man3/SSL_SESSION_set1_id.3 \
man/man3/SSL_accept.3 \
man/man3/SSL_alert_type_string.3 \
man/man3/SSL_alloc_buffers.3 \
man/man3/SSL_check_chain.3 \
man/man3/SSL_clear.3 \
man/man3/SSL_connect.3 \
man/man3/SSL_do_handshake.3 \
man/man3/SSL_export_keying_material.3 \
man/man3/SSL_extension_supported.3 \
man/man3/SSL_free.3 \
man/man3/SSL_get0_peer_scts.3 \
man/man3/SSL_get_SSL_CTX.3 \
man/man3/SSL_get_all_async_fds.3 \
man/man3/SSL_get_certificate.3 \
man/man3/SSL_get_ciphers.3 \
man/man3/SSL_get_client_random.3 \
man/man3/SSL_get_current_cipher.3 \
man/man3/SSL_get_default_timeout.3 \
man/man3/SSL_get_error.3 \
man/man3/SSL_get_extms_support.3 \
man/man3/SSL_get_fd.3 \
man/man3/SSL_get_peer_cert_chain.3 \
man/man3/SSL_get_peer_certificate.3 \
man/man3/SSL_get_peer_signature_nid.3 \
man/man3/SSL_get_peer_tmp_key.3 \
man/man3/SSL_get_psk_identity.3 \
man/man3/SSL_get_rbio.3 \
man/man3/SSL_get_session.3 \
man/man3/SSL_get_shared_sigalgs.3 \
man/man3/SSL_get_verify_result.3 \
man/man3/SSL_get_version.3 \
man/man3/SSL_group_to_name.3 \
man/man3/SSL_in_init.3 \
man/man3/SSL_key_update.3 \
man/man3/SSL_library_init.3 \
man/man3/SSL_load_client_CA_file.3 \
man/man3/SSL_new.3 \
man/man3/SSL_pending.3 \
man/man3/SSL_read.3 \
man/man3/SSL_read_early_data.3 \
man/man3/SSL_rstate_string.3 \
man/man3/SSL_session_reused.3 \
man/man3/SSL_set1_host.3 \
man/man3/SSL_set_async_callback.3 \
man/man3/SSL_set_bio.3 \
man/man3/SSL_set_connect_state.3 \
man/man3/SSL_set_fd.3 \
man/man3/SSL_set_retry_verify.3 \
man/man3/SSL_set_session.3 \
man/man3/SSL_set_shutdown.3 \
man/man3/SSL_set_verify_result.3 \
man/man3/SSL_shutdown.3 \
man/man3/SSL_state_string.3 \
man/man3/SSL_want.3 \
man/man3/SSL_write.3 \
man/man3/TS_RESP_CTX_new.3 \
man/man3/TS_VERIFY_CTX_set_certs.3 \
man/man3/UI_STRING.3 \
man/man3/UI_UTIL_read_pw.3 \
man/man3/UI_create_method.3 \
man/man3/UI_new.3 \
man/man3/X509V3_get_d2i.3 \
man/man3/X509V3_set_ctx.3 \
man/man3/X509_ALGOR_dup.3 \
man/man3/X509_CRL_get0_by_serial.3 \
man/man3/X509_EXTENSION_set_object.3 \
man/man3/X509_LOOKUP.3 \
man/man3/X509_LOOKUP_hash_dir.3 \
man/man3/X509_LOOKUP_meth_new.3 \
man/man3/X509_NAME_ENTRY_get_object.3 \
man/man3/X509_NAME_add_entry_by_txt.3 \
man/man3/X509_NAME_get0_der.3 \
man/man3/X509_NAME_get_index_by_NID.3 \
man/man3/X509_NAME_print_ex.3 \
man/man3/X509_PUBKEY_new.3 \
man/man3/X509_SIG_get0.3 \
man/man3/X509_STORE_CTX_get_error.3 \
man/man3/X509_STORE_CTX_new.3 \
man/man3/X509_STORE_CTX_set_verify_cb.3 \
man/man3/X509_STORE_add_cert.3 \
man/man3/X509_STORE_get0_param.3 \
man/man3/X509_STORE_new.3 \
man/man3/X509_STORE_set_verify_cb_func.3 \
man/man3/X509_VERIFY_PARAM_set_flags.3 \
man/man3/X509_add_cert.3 \
man/man3/X509_check_ca.3 \
man/man3/X509_check_host.3 \
man/man3/X509_check_issued.3 \
man/man3/X509_check_private_key.3 \
man/man3/X509_check_purpose.3 \
man/man3/X509_cmp.3 \
man/man3/X509_cmp_time.3 \
man/man3/X509_digest.3 \
man/man3/X509_dup.3 \
man/man3/X509_get0_distinguishing_id.3 \
man/man3/X509_get0_notBefore.3 \
man/man3/X509_get0_signature.3 \
man/man3/X509_get0_uids.3 \
man/man3/X509_get_extension_flags.3 \
man/man3/X509_get_pubkey.3 \
man/man3/X509_get_serialNumber.3 \
man/man3/X509_get_subject_name.3 \
man/man3/X509_get_version.3 \
man/man3/X509_load_http.3 \
man/man3/X509_new.3 \
man/man3/X509_sign.3 \
man/man3/X509_verify.3 \
man/man3/X509_verify_cert.3 \
man/man3/X509v3_get_ext_by_NID.3 \
man/man3/b2i_PVK_bio_ex.3 \
man/man3/d2i_PKCS8PrivateKey_bio.3 \
man/man3/d2i_PrivateKey.3 \
man/man3/d2i_RSAPrivateKey.3 \
man/man3/d2i_SSL_SESSION.3 \
man/man3/d2i_X509.3 \
man/man3/i2d_CMS_bio_stream.3 \
man/man3/i2d_PKCS7_bio_stream.3 \
man/man3/i2d_re_X509_tbs.3 \
man/man3/o2i_SCT_LIST.3 \
man/man3/s2i_ASN1_IA5STRING.3
DEPEND[html/man5/config.html]=man5/config.pod
GENERATE[html/man5/config.html]=man5/config.pod
DEPEND[man/man5/config.5]=man5/config.pod
GENERATE[man/man5/config.5]=man5/config.pod
DEPEND[html/man5/fips_config.html]=man5/fips_config.pod
GENERATE[html/man5/fips_config.html]=man5/fips_config.pod
DEPEND[man/man5/fips_config.5]=man5/fips_config.pod
GENERATE[man/man5/fips_config.5]=man5/fips_config.pod
DEPEND[html/man5/x509v3_config.html]=man5/x509v3_config.pod
GENERATE[html/man5/x509v3_config.html]=man5/x509v3_config.pod
DEPEND[man/man5/x509v3_config.5]=man5/x509v3_config.pod
GENERATE[man/man5/x509v3_config.5]=man5/x509v3_config.pod
IMAGEDOCS[man5]=
HTMLDOCS[man5]=html/man5/config.html \
html/man5/fips_config.html \
html/man5/x509v3_config.html
MANDOCS[man5]=man/man5/config.5 \
man/man5/fips_config.5 \
man/man5/x509v3_config.5
DEPEND[html/man7/EVP_ASYM_CIPHER-RSA.html]=man7/EVP_ASYM_CIPHER-RSA.pod
GENERATE[html/man7/EVP_ASYM_CIPHER-RSA.html]=man7/EVP_ASYM_CIPHER-RSA.pod
DEPEND[man/man7/EVP_ASYM_CIPHER-RSA.7]=man7/EVP_ASYM_CIPHER-RSA.pod
GENERATE[man/man7/EVP_ASYM_CIPHER-RSA.7]=man7/EVP_ASYM_CIPHER-RSA.pod
DEPEND[html/man7/EVP_ASYM_CIPHER-SM2.html]=man7/EVP_ASYM_CIPHER-SM2.pod
GENERATE[html/man7/EVP_ASYM_CIPHER-SM2.html]=man7/EVP_ASYM_CIPHER-SM2.pod
DEPEND[man/man7/EVP_ASYM_CIPHER-SM2.7]=man7/EVP_ASYM_CIPHER-SM2.pod
GENERATE[man/man7/EVP_ASYM_CIPHER-SM2.7]=man7/EVP_ASYM_CIPHER-SM2.pod
DEPEND[html/man7/EVP_CIPHER-AES.html]=man7/EVP_CIPHER-AES.pod
GENERATE[html/man7/EVP_CIPHER-AES.html]=man7/EVP_CIPHER-AES.pod
DEPEND[man/man7/EVP_CIPHER-AES.7]=man7/EVP_CIPHER-AES.pod
GENERATE[man/man7/EVP_CIPHER-AES.7]=man7/EVP_CIPHER-AES.pod
DEPEND[html/man7/EVP_CIPHER-ARIA.html]=man7/EVP_CIPHER-ARIA.pod
GENERATE[html/man7/EVP_CIPHER-ARIA.html]=man7/EVP_CIPHER-ARIA.pod
DEPEND[man/man7/EVP_CIPHER-ARIA.7]=man7/EVP_CIPHER-ARIA.pod
GENERATE[man/man7/EVP_CIPHER-ARIA.7]=man7/EVP_CIPHER-ARIA.pod
DEPEND[html/man7/EVP_CIPHER-BLOWFISH.html]=man7/EVP_CIPHER-BLOWFISH.pod
GENERATE[html/man7/EVP_CIPHER-BLOWFISH.html]=man7/EVP_CIPHER-BLOWFISH.pod
DEPEND[man/man7/EVP_CIPHER-BLOWFISH.7]=man7/EVP_CIPHER-BLOWFISH.pod
GENERATE[man/man7/EVP_CIPHER-BLOWFISH.7]=man7/EVP_CIPHER-BLOWFISH.pod
DEPEND[html/man7/EVP_CIPHER-CAMELLIA.html]=man7/EVP_CIPHER-CAMELLIA.pod
GENERATE[html/man7/EVP_CIPHER-CAMELLIA.html]=man7/EVP_CIPHER-CAMELLIA.pod
DEPEND[man/man7/EVP_CIPHER-CAMELLIA.7]=man7/EVP_CIPHER-CAMELLIA.pod
GENERATE[man/man7/EVP_CIPHER-CAMELLIA.7]=man7/EVP_CIPHER-CAMELLIA.pod
DEPEND[html/man7/EVP_CIPHER-CAST.html]=man7/EVP_CIPHER-CAST.pod
GENERATE[html/man7/EVP_CIPHER-CAST.html]=man7/EVP_CIPHER-CAST.pod
DEPEND[man/man7/EVP_CIPHER-CAST.7]=man7/EVP_CIPHER-CAST.pod
GENERATE[man/man7/EVP_CIPHER-CAST.7]=man7/EVP_CIPHER-CAST.pod
DEPEND[html/man7/EVP_CIPHER-CHACHA.html]=man7/EVP_CIPHER-CHACHA.pod
GENERATE[html/man7/EVP_CIPHER-CHACHA.html]=man7/EVP_CIPHER-CHACHA.pod
DEPEND[man/man7/EVP_CIPHER-CHACHA.7]=man7/EVP_CIPHER-CHACHA.pod
GENERATE[man/man7/EVP_CIPHER-CHACHA.7]=man7/EVP_CIPHER-CHACHA.pod
DEPEND[html/man7/EVP_CIPHER-DES.html]=man7/EVP_CIPHER-DES.pod
GENERATE[html/man7/EVP_CIPHER-DES.html]=man7/EVP_CIPHER-DES.pod
DEPEND[man/man7/EVP_CIPHER-DES.7]=man7/EVP_CIPHER-DES.pod
GENERATE[man/man7/EVP_CIPHER-DES.7]=man7/EVP_CIPHER-DES.pod
DEPEND[html/man7/EVP_CIPHER-IDEA.html]=man7/EVP_CIPHER-IDEA.pod
GENERATE[html/man7/EVP_CIPHER-IDEA.html]=man7/EVP_CIPHER-IDEA.pod
DEPEND[man/man7/EVP_CIPHER-IDEA.7]=man7/EVP_CIPHER-IDEA.pod
GENERATE[man/man7/EVP_CIPHER-IDEA.7]=man7/EVP_CIPHER-IDEA.pod
+DEPEND[html/man7/EVP_CIPHER-NULL.html]=man7/EVP_CIPHER-NULL.pod
+GENERATE[html/man7/EVP_CIPHER-NULL.html]=man7/EVP_CIPHER-NULL.pod
+DEPEND[man/man7/EVP_CIPHER-NULL.7]=man7/EVP_CIPHER-NULL.pod
+GENERATE[man/man7/EVP_CIPHER-NULL.7]=man7/EVP_CIPHER-NULL.pod
DEPEND[html/man7/EVP_CIPHER-RC2.html]=man7/EVP_CIPHER-RC2.pod
GENERATE[html/man7/EVP_CIPHER-RC2.html]=man7/EVP_CIPHER-RC2.pod
DEPEND[man/man7/EVP_CIPHER-RC2.7]=man7/EVP_CIPHER-RC2.pod
GENERATE[man/man7/EVP_CIPHER-RC2.7]=man7/EVP_CIPHER-RC2.pod
DEPEND[html/man7/EVP_CIPHER-RC4.html]=man7/EVP_CIPHER-RC4.pod
GENERATE[html/man7/EVP_CIPHER-RC4.html]=man7/EVP_CIPHER-RC4.pod
DEPEND[man/man7/EVP_CIPHER-RC4.7]=man7/EVP_CIPHER-RC4.pod
GENERATE[man/man7/EVP_CIPHER-RC4.7]=man7/EVP_CIPHER-RC4.pod
DEPEND[html/man7/EVP_CIPHER-RC5.html]=man7/EVP_CIPHER-RC5.pod
GENERATE[html/man7/EVP_CIPHER-RC5.html]=man7/EVP_CIPHER-RC5.pod
DEPEND[man/man7/EVP_CIPHER-RC5.7]=man7/EVP_CIPHER-RC5.pod
GENERATE[man/man7/EVP_CIPHER-RC5.7]=man7/EVP_CIPHER-RC5.pod
DEPEND[html/man7/EVP_CIPHER-SEED.html]=man7/EVP_CIPHER-SEED.pod
GENERATE[html/man7/EVP_CIPHER-SEED.html]=man7/EVP_CIPHER-SEED.pod
DEPEND[man/man7/EVP_CIPHER-SEED.7]=man7/EVP_CIPHER-SEED.pod
GENERATE[man/man7/EVP_CIPHER-SEED.7]=man7/EVP_CIPHER-SEED.pod
DEPEND[html/man7/EVP_CIPHER-SM4.html]=man7/EVP_CIPHER-SM4.pod
GENERATE[html/man7/EVP_CIPHER-SM4.html]=man7/EVP_CIPHER-SM4.pod
DEPEND[man/man7/EVP_CIPHER-SM4.7]=man7/EVP_CIPHER-SM4.pod
GENERATE[man/man7/EVP_CIPHER-SM4.7]=man7/EVP_CIPHER-SM4.pod
DEPEND[html/man7/EVP_KDF-HKDF.html]=man7/EVP_KDF-HKDF.pod
GENERATE[html/man7/EVP_KDF-HKDF.html]=man7/EVP_KDF-HKDF.pod
DEPEND[man/man7/EVP_KDF-HKDF.7]=man7/EVP_KDF-HKDF.pod
GENERATE[man/man7/EVP_KDF-HKDF.7]=man7/EVP_KDF-HKDF.pod
DEPEND[html/man7/EVP_KDF-KB.html]=man7/EVP_KDF-KB.pod
GENERATE[html/man7/EVP_KDF-KB.html]=man7/EVP_KDF-KB.pod
DEPEND[man/man7/EVP_KDF-KB.7]=man7/EVP_KDF-KB.pod
GENERATE[man/man7/EVP_KDF-KB.7]=man7/EVP_KDF-KB.pod
DEPEND[html/man7/EVP_KDF-KRB5KDF.html]=man7/EVP_KDF-KRB5KDF.pod
GENERATE[html/man7/EVP_KDF-KRB5KDF.html]=man7/EVP_KDF-KRB5KDF.pod
DEPEND[man/man7/EVP_KDF-KRB5KDF.7]=man7/EVP_KDF-KRB5KDF.pod
GENERATE[man/man7/EVP_KDF-KRB5KDF.7]=man7/EVP_KDF-KRB5KDF.pod
DEPEND[html/man7/EVP_KDF-PBKDF1.html]=man7/EVP_KDF-PBKDF1.pod
GENERATE[html/man7/EVP_KDF-PBKDF1.html]=man7/EVP_KDF-PBKDF1.pod
DEPEND[man/man7/EVP_KDF-PBKDF1.7]=man7/EVP_KDF-PBKDF1.pod
GENERATE[man/man7/EVP_KDF-PBKDF1.7]=man7/EVP_KDF-PBKDF1.pod
DEPEND[html/man7/EVP_KDF-PBKDF2.html]=man7/EVP_KDF-PBKDF2.pod
GENERATE[html/man7/EVP_KDF-PBKDF2.html]=man7/EVP_KDF-PBKDF2.pod
DEPEND[man/man7/EVP_KDF-PBKDF2.7]=man7/EVP_KDF-PBKDF2.pod
GENERATE[man/man7/EVP_KDF-PBKDF2.7]=man7/EVP_KDF-PBKDF2.pod
DEPEND[html/man7/EVP_KDF-PKCS12KDF.html]=man7/EVP_KDF-PKCS12KDF.pod
GENERATE[html/man7/EVP_KDF-PKCS12KDF.html]=man7/EVP_KDF-PKCS12KDF.pod
DEPEND[man/man7/EVP_KDF-PKCS12KDF.7]=man7/EVP_KDF-PKCS12KDF.pod
GENERATE[man/man7/EVP_KDF-PKCS12KDF.7]=man7/EVP_KDF-PKCS12KDF.pod
DEPEND[html/man7/EVP_KDF-SCRYPT.html]=man7/EVP_KDF-SCRYPT.pod
GENERATE[html/man7/EVP_KDF-SCRYPT.html]=man7/EVP_KDF-SCRYPT.pod
DEPEND[man/man7/EVP_KDF-SCRYPT.7]=man7/EVP_KDF-SCRYPT.pod
GENERATE[man/man7/EVP_KDF-SCRYPT.7]=man7/EVP_KDF-SCRYPT.pod
DEPEND[html/man7/EVP_KDF-SS.html]=man7/EVP_KDF-SS.pod
GENERATE[html/man7/EVP_KDF-SS.html]=man7/EVP_KDF-SS.pod
DEPEND[man/man7/EVP_KDF-SS.7]=man7/EVP_KDF-SS.pod
GENERATE[man/man7/EVP_KDF-SS.7]=man7/EVP_KDF-SS.pod
DEPEND[html/man7/EVP_KDF-SSHKDF.html]=man7/EVP_KDF-SSHKDF.pod
GENERATE[html/man7/EVP_KDF-SSHKDF.html]=man7/EVP_KDF-SSHKDF.pod
DEPEND[man/man7/EVP_KDF-SSHKDF.7]=man7/EVP_KDF-SSHKDF.pod
GENERATE[man/man7/EVP_KDF-SSHKDF.7]=man7/EVP_KDF-SSHKDF.pod
DEPEND[html/man7/EVP_KDF-TLS13_KDF.html]=man7/EVP_KDF-TLS13_KDF.pod
GENERATE[html/man7/EVP_KDF-TLS13_KDF.html]=man7/EVP_KDF-TLS13_KDF.pod
DEPEND[man/man7/EVP_KDF-TLS13_KDF.7]=man7/EVP_KDF-TLS13_KDF.pod
GENERATE[man/man7/EVP_KDF-TLS13_KDF.7]=man7/EVP_KDF-TLS13_KDF.pod
DEPEND[html/man7/EVP_KDF-TLS1_PRF.html]=man7/EVP_KDF-TLS1_PRF.pod
GENERATE[html/man7/EVP_KDF-TLS1_PRF.html]=man7/EVP_KDF-TLS1_PRF.pod
DEPEND[man/man7/EVP_KDF-TLS1_PRF.7]=man7/EVP_KDF-TLS1_PRF.pod
GENERATE[man/man7/EVP_KDF-TLS1_PRF.7]=man7/EVP_KDF-TLS1_PRF.pod
DEPEND[html/man7/EVP_KDF-X942-ASN1.html]=man7/EVP_KDF-X942-ASN1.pod
GENERATE[html/man7/EVP_KDF-X942-ASN1.html]=man7/EVP_KDF-X942-ASN1.pod
DEPEND[man/man7/EVP_KDF-X942-ASN1.7]=man7/EVP_KDF-X942-ASN1.pod
GENERATE[man/man7/EVP_KDF-X942-ASN1.7]=man7/EVP_KDF-X942-ASN1.pod
DEPEND[html/man7/EVP_KDF-X942-CONCAT.html]=man7/EVP_KDF-X942-CONCAT.pod
GENERATE[html/man7/EVP_KDF-X942-CONCAT.html]=man7/EVP_KDF-X942-CONCAT.pod
DEPEND[man/man7/EVP_KDF-X942-CONCAT.7]=man7/EVP_KDF-X942-CONCAT.pod
GENERATE[man/man7/EVP_KDF-X942-CONCAT.7]=man7/EVP_KDF-X942-CONCAT.pod
DEPEND[html/man7/EVP_KDF-X963.html]=man7/EVP_KDF-X963.pod
GENERATE[html/man7/EVP_KDF-X963.html]=man7/EVP_KDF-X963.pod
DEPEND[man/man7/EVP_KDF-X963.7]=man7/EVP_KDF-X963.pod
GENERATE[man/man7/EVP_KDF-X963.7]=man7/EVP_KDF-X963.pod
DEPEND[html/man7/EVP_KEM-RSA.html]=man7/EVP_KEM-RSA.pod
GENERATE[html/man7/EVP_KEM-RSA.html]=man7/EVP_KEM-RSA.pod
DEPEND[man/man7/EVP_KEM-RSA.7]=man7/EVP_KEM-RSA.pod
GENERATE[man/man7/EVP_KEM-RSA.7]=man7/EVP_KEM-RSA.pod
DEPEND[html/man7/EVP_KEYEXCH-DH.html]=man7/EVP_KEYEXCH-DH.pod
GENERATE[html/man7/EVP_KEYEXCH-DH.html]=man7/EVP_KEYEXCH-DH.pod
DEPEND[man/man7/EVP_KEYEXCH-DH.7]=man7/EVP_KEYEXCH-DH.pod
GENERATE[man/man7/EVP_KEYEXCH-DH.7]=man7/EVP_KEYEXCH-DH.pod
DEPEND[html/man7/EVP_KEYEXCH-ECDH.html]=man7/EVP_KEYEXCH-ECDH.pod
GENERATE[html/man7/EVP_KEYEXCH-ECDH.html]=man7/EVP_KEYEXCH-ECDH.pod
DEPEND[man/man7/EVP_KEYEXCH-ECDH.7]=man7/EVP_KEYEXCH-ECDH.pod
GENERATE[man/man7/EVP_KEYEXCH-ECDH.7]=man7/EVP_KEYEXCH-ECDH.pod
DEPEND[html/man7/EVP_KEYEXCH-X25519.html]=man7/EVP_KEYEXCH-X25519.pod
GENERATE[html/man7/EVP_KEYEXCH-X25519.html]=man7/EVP_KEYEXCH-X25519.pod
DEPEND[man/man7/EVP_KEYEXCH-X25519.7]=man7/EVP_KEYEXCH-X25519.pod
GENERATE[man/man7/EVP_KEYEXCH-X25519.7]=man7/EVP_KEYEXCH-X25519.pod
DEPEND[html/man7/EVP_MAC-BLAKE2.html]=man7/EVP_MAC-BLAKE2.pod
GENERATE[html/man7/EVP_MAC-BLAKE2.html]=man7/EVP_MAC-BLAKE2.pod
DEPEND[man/man7/EVP_MAC-BLAKE2.7]=man7/EVP_MAC-BLAKE2.pod
GENERATE[man/man7/EVP_MAC-BLAKE2.7]=man7/EVP_MAC-BLAKE2.pod
DEPEND[html/man7/EVP_MAC-CMAC.html]=man7/EVP_MAC-CMAC.pod
GENERATE[html/man7/EVP_MAC-CMAC.html]=man7/EVP_MAC-CMAC.pod
DEPEND[man/man7/EVP_MAC-CMAC.7]=man7/EVP_MAC-CMAC.pod
GENERATE[man/man7/EVP_MAC-CMAC.7]=man7/EVP_MAC-CMAC.pod
DEPEND[html/man7/EVP_MAC-GMAC.html]=man7/EVP_MAC-GMAC.pod
GENERATE[html/man7/EVP_MAC-GMAC.html]=man7/EVP_MAC-GMAC.pod
DEPEND[man/man7/EVP_MAC-GMAC.7]=man7/EVP_MAC-GMAC.pod
GENERATE[man/man7/EVP_MAC-GMAC.7]=man7/EVP_MAC-GMAC.pod
DEPEND[html/man7/EVP_MAC-HMAC.html]=man7/EVP_MAC-HMAC.pod
GENERATE[html/man7/EVP_MAC-HMAC.html]=man7/EVP_MAC-HMAC.pod
DEPEND[man/man7/EVP_MAC-HMAC.7]=man7/EVP_MAC-HMAC.pod
GENERATE[man/man7/EVP_MAC-HMAC.7]=man7/EVP_MAC-HMAC.pod
DEPEND[html/man7/EVP_MAC-KMAC.html]=man7/EVP_MAC-KMAC.pod
GENERATE[html/man7/EVP_MAC-KMAC.html]=man7/EVP_MAC-KMAC.pod
DEPEND[man/man7/EVP_MAC-KMAC.7]=man7/EVP_MAC-KMAC.pod
GENERATE[man/man7/EVP_MAC-KMAC.7]=man7/EVP_MAC-KMAC.pod
DEPEND[html/man7/EVP_MAC-Poly1305.html]=man7/EVP_MAC-Poly1305.pod
GENERATE[html/man7/EVP_MAC-Poly1305.html]=man7/EVP_MAC-Poly1305.pod
DEPEND[man/man7/EVP_MAC-Poly1305.7]=man7/EVP_MAC-Poly1305.pod
GENERATE[man/man7/EVP_MAC-Poly1305.7]=man7/EVP_MAC-Poly1305.pod
DEPEND[html/man7/EVP_MAC-Siphash.html]=man7/EVP_MAC-Siphash.pod
GENERATE[html/man7/EVP_MAC-Siphash.html]=man7/EVP_MAC-Siphash.pod
DEPEND[man/man7/EVP_MAC-Siphash.7]=man7/EVP_MAC-Siphash.pod
GENERATE[man/man7/EVP_MAC-Siphash.7]=man7/EVP_MAC-Siphash.pod
DEPEND[html/man7/EVP_MD-BLAKE2.html]=man7/EVP_MD-BLAKE2.pod
GENERATE[html/man7/EVP_MD-BLAKE2.html]=man7/EVP_MD-BLAKE2.pod
DEPEND[man/man7/EVP_MD-BLAKE2.7]=man7/EVP_MD-BLAKE2.pod
GENERATE[man/man7/EVP_MD-BLAKE2.7]=man7/EVP_MD-BLAKE2.pod
DEPEND[html/man7/EVP_MD-MD2.html]=man7/EVP_MD-MD2.pod
GENERATE[html/man7/EVP_MD-MD2.html]=man7/EVP_MD-MD2.pod
DEPEND[man/man7/EVP_MD-MD2.7]=man7/EVP_MD-MD2.pod
GENERATE[man/man7/EVP_MD-MD2.7]=man7/EVP_MD-MD2.pod
DEPEND[html/man7/EVP_MD-MD4.html]=man7/EVP_MD-MD4.pod
GENERATE[html/man7/EVP_MD-MD4.html]=man7/EVP_MD-MD4.pod
DEPEND[man/man7/EVP_MD-MD4.7]=man7/EVP_MD-MD4.pod
GENERATE[man/man7/EVP_MD-MD4.7]=man7/EVP_MD-MD4.pod
DEPEND[html/man7/EVP_MD-MD5-SHA1.html]=man7/EVP_MD-MD5-SHA1.pod
GENERATE[html/man7/EVP_MD-MD5-SHA1.html]=man7/EVP_MD-MD5-SHA1.pod
DEPEND[man/man7/EVP_MD-MD5-SHA1.7]=man7/EVP_MD-MD5-SHA1.pod
GENERATE[man/man7/EVP_MD-MD5-SHA1.7]=man7/EVP_MD-MD5-SHA1.pod
DEPEND[html/man7/EVP_MD-MD5.html]=man7/EVP_MD-MD5.pod
GENERATE[html/man7/EVP_MD-MD5.html]=man7/EVP_MD-MD5.pod
DEPEND[man/man7/EVP_MD-MD5.7]=man7/EVP_MD-MD5.pod
GENERATE[man/man7/EVP_MD-MD5.7]=man7/EVP_MD-MD5.pod
DEPEND[html/man7/EVP_MD-MDC2.html]=man7/EVP_MD-MDC2.pod
GENERATE[html/man7/EVP_MD-MDC2.html]=man7/EVP_MD-MDC2.pod
DEPEND[man/man7/EVP_MD-MDC2.7]=man7/EVP_MD-MDC2.pod
GENERATE[man/man7/EVP_MD-MDC2.7]=man7/EVP_MD-MDC2.pod
+DEPEND[html/man7/EVP_MD-NULL.html]=man7/EVP_MD-NULL.pod
+GENERATE[html/man7/EVP_MD-NULL.html]=man7/EVP_MD-NULL.pod
+DEPEND[man/man7/EVP_MD-NULL.7]=man7/EVP_MD-NULL.pod
+GENERATE[man/man7/EVP_MD-NULL.7]=man7/EVP_MD-NULL.pod
DEPEND[html/man7/EVP_MD-RIPEMD160.html]=man7/EVP_MD-RIPEMD160.pod
GENERATE[html/man7/EVP_MD-RIPEMD160.html]=man7/EVP_MD-RIPEMD160.pod
DEPEND[man/man7/EVP_MD-RIPEMD160.7]=man7/EVP_MD-RIPEMD160.pod
GENERATE[man/man7/EVP_MD-RIPEMD160.7]=man7/EVP_MD-RIPEMD160.pod
DEPEND[html/man7/EVP_MD-SHA1.html]=man7/EVP_MD-SHA1.pod
GENERATE[html/man7/EVP_MD-SHA1.html]=man7/EVP_MD-SHA1.pod
DEPEND[man/man7/EVP_MD-SHA1.7]=man7/EVP_MD-SHA1.pod
GENERATE[man/man7/EVP_MD-SHA1.7]=man7/EVP_MD-SHA1.pod
DEPEND[html/man7/EVP_MD-SHA2.html]=man7/EVP_MD-SHA2.pod
GENERATE[html/man7/EVP_MD-SHA2.html]=man7/EVP_MD-SHA2.pod
DEPEND[man/man7/EVP_MD-SHA2.7]=man7/EVP_MD-SHA2.pod
GENERATE[man/man7/EVP_MD-SHA2.7]=man7/EVP_MD-SHA2.pod
DEPEND[html/man7/EVP_MD-SHA3.html]=man7/EVP_MD-SHA3.pod
GENERATE[html/man7/EVP_MD-SHA3.html]=man7/EVP_MD-SHA3.pod
DEPEND[man/man7/EVP_MD-SHA3.7]=man7/EVP_MD-SHA3.pod
GENERATE[man/man7/EVP_MD-SHA3.7]=man7/EVP_MD-SHA3.pod
DEPEND[html/man7/EVP_MD-SHAKE.html]=man7/EVP_MD-SHAKE.pod
GENERATE[html/man7/EVP_MD-SHAKE.html]=man7/EVP_MD-SHAKE.pod
DEPEND[man/man7/EVP_MD-SHAKE.7]=man7/EVP_MD-SHAKE.pod
GENERATE[man/man7/EVP_MD-SHAKE.7]=man7/EVP_MD-SHAKE.pod
DEPEND[html/man7/EVP_MD-SM3.html]=man7/EVP_MD-SM3.pod
GENERATE[html/man7/EVP_MD-SM3.html]=man7/EVP_MD-SM3.pod
DEPEND[man/man7/EVP_MD-SM3.7]=man7/EVP_MD-SM3.pod
GENERATE[man/man7/EVP_MD-SM3.7]=man7/EVP_MD-SM3.pod
DEPEND[html/man7/EVP_MD-WHIRLPOOL.html]=man7/EVP_MD-WHIRLPOOL.pod
GENERATE[html/man7/EVP_MD-WHIRLPOOL.html]=man7/EVP_MD-WHIRLPOOL.pod
DEPEND[man/man7/EVP_MD-WHIRLPOOL.7]=man7/EVP_MD-WHIRLPOOL.pod
GENERATE[man/man7/EVP_MD-WHIRLPOOL.7]=man7/EVP_MD-WHIRLPOOL.pod
DEPEND[html/man7/EVP_MD-common.html]=man7/EVP_MD-common.pod
GENERATE[html/man7/EVP_MD-common.html]=man7/EVP_MD-common.pod
DEPEND[man/man7/EVP_MD-common.7]=man7/EVP_MD-common.pod
GENERATE[man/man7/EVP_MD-common.7]=man7/EVP_MD-common.pod
DEPEND[html/man7/EVP_PKEY-DH.html]=man7/EVP_PKEY-DH.pod
GENERATE[html/man7/EVP_PKEY-DH.html]=man7/EVP_PKEY-DH.pod
DEPEND[man/man7/EVP_PKEY-DH.7]=man7/EVP_PKEY-DH.pod
GENERATE[man/man7/EVP_PKEY-DH.7]=man7/EVP_PKEY-DH.pod
DEPEND[html/man7/EVP_PKEY-DSA.html]=man7/EVP_PKEY-DSA.pod
GENERATE[html/man7/EVP_PKEY-DSA.html]=man7/EVP_PKEY-DSA.pod
DEPEND[man/man7/EVP_PKEY-DSA.7]=man7/EVP_PKEY-DSA.pod
GENERATE[man/man7/EVP_PKEY-DSA.7]=man7/EVP_PKEY-DSA.pod
DEPEND[html/man7/EVP_PKEY-EC.html]=man7/EVP_PKEY-EC.pod
GENERATE[html/man7/EVP_PKEY-EC.html]=man7/EVP_PKEY-EC.pod
DEPEND[man/man7/EVP_PKEY-EC.7]=man7/EVP_PKEY-EC.pod
GENERATE[man/man7/EVP_PKEY-EC.7]=man7/EVP_PKEY-EC.pod
DEPEND[html/man7/EVP_PKEY-FFC.html]=man7/EVP_PKEY-FFC.pod
GENERATE[html/man7/EVP_PKEY-FFC.html]=man7/EVP_PKEY-FFC.pod
DEPEND[man/man7/EVP_PKEY-FFC.7]=man7/EVP_PKEY-FFC.pod
GENERATE[man/man7/EVP_PKEY-FFC.7]=man7/EVP_PKEY-FFC.pod
DEPEND[html/man7/EVP_PKEY-HMAC.html]=man7/EVP_PKEY-HMAC.pod
GENERATE[html/man7/EVP_PKEY-HMAC.html]=man7/EVP_PKEY-HMAC.pod
DEPEND[man/man7/EVP_PKEY-HMAC.7]=man7/EVP_PKEY-HMAC.pod
GENERATE[man/man7/EVP_PKEY-HMAC.7]=man7/EVP_PKEY-HMAC.pod
DEPEND[html/man7/EVP_PKEY-RSA.html]=man7/EVP_PKEY-RSA.pod
GENERATE[html/man7/EVP_PKEY-RSA.html]=man7/EVP_PKEY-RSA.pod
DEPEND[man/man7/EVP_PKEY-RSA.7]=man7/EVP_PKEY-RSA.pod
GENERATE[man/man7/EVP_PKEY-RSA.7]=man7/EVP_PKEY-RSA.pod
DEPEND[html/man7/EVP_PKEY-SM2.html]=man7/EVP_PKEY-SM2.pod
GENERATE[html/man7/EVP_PKEY-SM2.html]=man7/EVP_PKEY-SM2.pod
DEPEND[man/man7/EVP_PKEY-SM2.7]=man7/EVP_PKEY-SM2.pod
GENERATE[man/man7/EVP_PKEY-SM2.7]=man7/EVP_PKEY-SM2.pod
DEPEND[html/man7/EVP_PKEY-X25519.html]=man7/EVP_PKEY-X25519.pod
GENERATE[html/man7/EVP_PKEY-X25519.html]=man7/EVP_PKEY-X25519.pod
DEPEND[man/man7/EVP_PKEY-X25519.7]=man7/EVP_PKEY-X25519.pod
GENERATE[man/man7/EVP_PKEY-X25519.7]=man7/EVP_PKEY-X25519.pod
DEPEND[html/man7/EVP_RAND-CTR-DRBG.html]=man7/EVP_RAND-CTR-DRBG.pod
GENERATE[html/man7/EVP_RAND-CTR-DRBG.html]=man7/EVP_RAND-CTR-DRBG.pod
DEPEND[man/man7/EVP_RAND-CTR-DRBG.7]=man7/EVP_RAND-CTR-DRBG.pod
GENERATE[man/man7/EVP_RAND-CTR-DRBG.7]=man7/EVP_RAND-CTR-DRBG.pod
DEPEND[html/man7/EVP_RAND-HASH-DRBG.html]=man7/EVP_RAND-HASH-DRBG.pod
GENERATE[html/man7/EVP_RAND-HASH-DRBG.html]=man7/EVP_RAND-HASH-DRBG.pod
DEPEND[man/man7/EVP_RAND-HASH-DRBG.7]=man7/EVP_RAND-HASH-DRBG.pod
GENERATE[man/man7/EVP_RAND-HASH-DRBG.7]=man7/EVP_RAND-HASH-DRBG.pod
DEPEND[html/man7/EVP_RAND-HMAC-DRBG.html]=man7/EVP_RAND-HMAC-DRBG.pod
GENERATE[html/man7/EVP_RAND-HMAC-DRBG.html]=man7/EVP_RAND-HMAC-DRBG.pod
DEPEND[man/man7/EVP_RAND-HMAC-DRBG.7]=man7/EVP_RAND-HMAC-DRBG.pod
GENERATE[man/man7/EVP_RAND-HMAC-DRBG.7]=man7/EVP_RAND-HMAC-DRBG.pod
DEPEND[html/man7/EVP_RAND-SEED-SRC.html]=man7/EVP_RAND-SEED-SRC.pod
GENERATE[html/man7/EVP_RAND-SEED-SRC.html]=man7/EVP_RAND-SEED-SRC.pod
DEPEND[man/man7/EVP_RAND-SEED-SRC.7]=man7/EVP_RAND-SEED-SRC.pod
GENERATE[man/man7/EVP_RAND-SEED-SRC.7]=man7/EVP_RAND-SEED-SRC.pod
DEPEND[html/man7/EVP_RAND-TEST-RAND.html]=man7/EVP_RAND-TEST-RAND.pod
GENERATE[html/man7/EVP_RAND-TEST-RAND.html]=man7/EVP_RAND-TEST-RAND.pod
DEPEND[man/man7/EVP_RAND-TEST-RAND.7]=man7/EVP_RAND-TEST-RAND.pod
GENERATE[man/man7/EVP_RAND-TEST-RAND.7]=man7/EVP_RAND-TEST-RAND.pod
DEPEND[html/man7/EVP_RAND.html]=man7/EVP_RAND.pod
GENERATE[html/man7/EVP_RAND.html]=man7/EVP_RAND.pod
DEPEND[man/man7/EVP_RAND.7]=man7/EVP_RAND.pod
GENERATE[man/man7/EVP_RAND.7]=man7/EVP_RAND.pod
DEPEND[html/man7/EVP_SIGNATURE-DSA.html]=man7/EVP_SIGNATURE-DSA.pod
GENERATE[html/man7/EVP_SIGNATURE-DSA.html]=man7/EVP_SIGNATURE-DSA.pod
DEPEND[man/man7/EVP_SIGNATURE-DSA.7]=man7/EVP_SIGNATURE-DSA.pod
GENERATE[man/man7/EVP_SIGNATURE-DSA.7]=man7/EVP_SIGNATURE-DSA.pod
DEPEND[html/man7/EVP_SIGNATURE-ECDSA.html]=man7/EVP_SIGNATURE-ECDSA.pod
GENERATE[html/man7/EVP_SIGNATURE-ECDSA.html]=man7/EVP_SIGNATURE-ECDSA.pod
DEPEND[man/man7/EVP_SIGNATURE-ECDSA.7]=man7/EVP_SIGNATURE-ECDSA.pod
GENERATE[man/man7/EVP_SIGNATURE-ECDSA.7]=man7/EVP_SIGNATURE-ECDSA.pod
DEPEND[html/man7/EVP_SIGNATURE-ED25519.html]=man7/EVP_SIGNATURE-ED25519.pod
GENERATE[html/man7/EVP_SIGNATURE-ED25519.html]=man7/EVP_SIGNATURE-ED25519.pod
DEPEND[man/man7/EVP_SIGNATURE-ED25519.7]=man7/EVP_SIGNATURE-ED25519.pod
GENERATE[man/man7/EVP_SIGNATURE-ED25519.7]=man7/EVP_SIGNATURE-ED25519.pod
DEPEND[html/man7/EVP_SIGNATURE-HMAC.html]=man7/EVP_SIGNATURE-HMAC.pod
GENERATE[html/man7/EVP_SIGNATURE-HMAC.html]=man7/EVP_SIGNATURE-HMAC.pod
DEPEND[man/man7/EVP_SIGNATURE-HMAC.7]=man7/EVP_SIGNATURE-HMAC.pod
GENERATE[man/man7/EVP_SIGNATURE-HMAC.7]=man7/EVP_SIGNATURE-HMAC.pod
DEPEND[html/man7/EVP_SIGNATURE-RSA.html]=man7/EVP_SIGNATURE-RSA.pod
GENERATE[html/man7/EVP_SIGNATURE-RSA.html]=man7/EVP_SIGNATURE-RSA.pod
DEPEND[man/man7/EVP_SIGNATURE-RSA.7]=man7/EVP_SIGNATURE-RSA.pod
GENERATE[man/man7/EVP_SIGNATURE-RSA.7]=man7/EVP_SIGNATURE-RSA.pod
DEPEND[html/man7/OSSL_PROVIDER-FIPS.html]=man7/OSSL_PROVIDER-FIPS.pod
GENERATE[html/man7/OSSL_PROVIDER-FIPS.html]=man7/OSSL_PROVIDER-FIPS.pod
DEPEND[man/man7/OSSL_PROVIDER-FIPS.7]=man7/OSSL_PROVIDER-FIPS.pod
GENERATE[man/man7/OSSL_PROVIDER-FIPS.7]=man7/OSSL_PROVIDER-FIPS.pod
DEPEND[html/man7/OSSL_PROVIDER-base.html]=man7/OSSL_PROVIDER-base.pod
GENERATE[html/man7/OSSL_PROVIDER-base.html]=man7/OSSL_PROVIDER-base.pod
DEPEND[man/man7/OSSL_PROVIDER-base.7]=man7/OSSL_PROVIDER-base.pod
GENERATE[man/man7/OSSL_PROVIDER-base.7]=man7/OSSL_PROVIDER-base.pod
DEPEND[html/man7/OSSL_PROVIDER-default.html]=man7/OSSL_PROVIDER-default.pod
GENERATE[html/man7/OSSL_PROVIDER-default.html]=man7/OSSL_PROVIDER-default.pod
DEPEND[man/man7/OSSL_PROVIDER-default.7]=man7/OSSL_PROVIDER-default.pod
GENERATE[man/man7/OSSL_PROVIDER-default.7]=man7/OSSL_PROVIDER-default.pod
DEPEND[html/man7/OSSL_PROVIDER-legacy.html]=man7/OSSL_PROVIDER-legacy.pod
GENERATE[html/man7/OSSL_PROVIDER-legacy.html]=man7/OSSL_PROVIDER-legacy.pod
DEPEND[man/man7/OSSL_PROVIDER-legacy.7]=man7/OSSL_PROVIDER-legacy.pod
GENERATE[man/man7/OSSL_PROVIDER-legacy.7]=man7/OSSL_PROVIDER-legacy.pod
DEPEND[html/man7/OSSL_PROVIDER-null.html]=man7/OSSL_PROVIDER-null.pod
GENERATE[html/man7/OSSL_PROVIDER-null.html]=man7/OSSL_PROVIDER-null.pod
DEPEND[man/man7/OSSL_PROVIDER-null.7]=man7/OSSL_PROVIDER-null.pod
GENERATE[man/man7/OSSL_PROVIDER-null.7]=man7/OSSL_PROVIDER-null.pod
DEPEND[html/man7/RAND.html]=man7/RAND.pod
GENERATE[html/man7/RAND.html]=man7/RAND.pod
DEPEND[man/man7/RAND.7]=man7/RAND.pod
GENERATE[man/man7/RAND.7]=man7/RAND.pod
DEPEND[html/man7/RSA-PSS.html]=man7/RSA-PSS.pod
GENERATE[html/man7/RSA-PSS.html]=man7/RSA-PSS.pod
DEPEND[man/man7/RSA-PSS.7]=man7/RSA-PSS.pod
GENERATE[man/man7/RSA-PSS.7]=man7/RSA-PSS.pod
DEPEND[html/man7/X25519.html]=man7/X25519.pod
GENERATE[html/man7/X25519.html]=man7/X25519.pod
DEPEND[man/man7/X25519.7]=man7/X25519.pod
GENERATE[man/man7/X25519.7]=man7/X25519.pod
DEPEND[html/man7/bio.html]=man7/bio.pod
GENERATE[html/man7/bio.html]=man7/bio.pod
DEPEND[man/man7/bio.7]=man7/bio.pod
GENERATE[man/man7/bio.7]=man7/bio.pod
DEPEND[html/man7/crypto.html]=man7/crypto.pod
GENERATE[html/man7/crypto.html]=man7/crypto.pod
DEPEND[man/man7/crypto.7]=man7/crypto.pod
GENERATE[man/man7/crypto.7]=man7/crypto.pod
DEPEND[html/man7/ct.html]=man7/ct.pod
GENERATE[html/man7/ct.html]=man7/ct.pod
DEPEND[man/man7/ct.7]=man7/ct.pod
GENERATE[man/man7/ct.7]=man7/ct.pod
DEPEND[html/man7/des_modes.html]=man7/des_modes.pod
GENERATE[html/man7/des_modes.html]=man7/des_modes.pod
DEPEND[man/man7/des_modes.7]=man7/des_modes.pod
GENERATE[man/man7/des_modes.7]=man7/des_modes.pod
DEPEND[html/man7/evp.html]=man7/evp.pod
GENERATE[html/man7/evp.html]=man7/evp.pod
DEPEND[man/man7/evp.7]=man7/evp.pod
GENERATE[man/man7/evp.7]=man7/evp.pod
DEPEND[html/man7/fips_module.html]=man7/fips_module.pod
GENERATE[html/man7/fips_module.html]=man7/fips_module.pod
DEPEND[man/man7/fips_module.7]=man7/fips_module.pod
GENERATE[man/man7/fips_module.7]=man7/fips_module.pod
DEPEND[html/man7/life_cycle-cipher.html]=man7/life_cycle-cipher.pod
GENERATE[html/man7/life_cycle-cipher.html]=man7/life_cycle-cipher.pod
DEPEND[man/man7/life_cycle-cipher.7]=man7/life_cycle-cipher.pod
GENERATE[man/man7/life_cycle-cipher.7]=man7/life_cycle-cipher.pod
DEPEND[html/man7/life_cycle-digest.html]=man7/life_cycle-digest.pod
GENERATE[html/man7/life_cycle-digest.html]=man7/life_cycle-digest.pod
DEPEND[man/man7/life_cycle-digest.7]=man7/life_cycle-digest.pod
GENERATE[man/man7/life_cycle-digest.7]=man7/life_cycle-digest.pod
DEPEND[html/man7/life_cycle-kdf.html]=man7/life_cycle-kdf.pod
GENERATE[html/man7/life_cycle-kdf.html]=man7/life_cycle-kdf.pod
DEPEND[man/man7/life_cycle-kdf.7]=man7/life_cycle-kdf.pod
GENERATE[man/man7/life_cycle-kdf.7]=man7/life_cycle-kdf.pod
DEPEND[html/man7/life_cycle-mac.html]=man7/life_cycle-mac.pod
GENERATE[html/man7/life_cycle-mac.html]=man7/life_cycle-mac.pod
DEPEND[man/man7/life_cycle-mac.7]=man7/life_cycle-mac.pod
GENERATE[man/man7/life_cycle-mac.7]=man7/life_cycle-mac.pod
DEPEND[html/man7/life_cycle-pkey.html]=man7/life_cycle-pkey.pod
GENERATE[html/man7/life_cycle-pkey.html]=man7/life_cycle-pkey.pod
DEPEND[man/man7/life_cycle-pkey.7]=man7/life_cycle-pkey.pod
GENERATE[man/man7/life_cycle-pkey.7]=man7/life_cycle-pkey.pod
DEPEND[html/man7/life_cycle-rand.html]=man7/life_cycle-rand.pod
GENERATE[html/man7/life_cycle-rand.html]=man7/life_cycle-rand.pod
DEPEND[man/man7/life_cycle-rand.7]=man7/life_cycle-rand.pod
GENERATE[man/man7/life_cycle-rand.7]=man7/life_cycle-rand.pod
DEPEND[html/man7/migration_guide.html]=man7/migration_guide.pod
GENERATE[html/man7/migration_guide.html]=man7/migration_guide.pod
DEPEND[man/man7/migration_guide.7]=man7/migration_guide.pod
GENERATE[man/man7/migration_guide.7]=man7/migration_guide.pod
DEPEND[html/man7/openssl-core.h.html]=man7/openssl-core.h.pod
GENERATE[html/man7/openssl-core.h.html]=man7/openssl-core.h.pod
DEPEND[man/man7/openssl-core.h.7]=man7/openssl-core.h.pod
GENERATE[man/man7/openssl-core.h.7]=man7/openssl-core.h.pod
DEPEND[html/man7/openssl-core_dispatch.h.html]=man7/openssl-core_dispatch.h.pod
GENERATE[html/man7/openssl-core_dispatch.h.html]=man7/openssl-core_dispatch.h.pod
DEPEND[man/man7/openssl-core_dispatch.h.7]=man7/openssl-core_dispatch.h.pod
GENERATE[man/man7/openssl-core_dispatch.h.7]=man7/openssl-core_dispatch.h.pod
DEPEND[html/man7/openssl-core_names.h.html]=man7/openssl-core_names.h.pod
GENERATE[html/man7/openssl-core_names.h.html]=man7/openssl-core_names.h.pod
DEPEND[man/man7/openssl-core_names.h.7]=man7/openssl-core_names.h.pod
GENERATE[man/man7/openssl-core_names.h.7]=man7/openssl-core_names.h.pod
DEPEND[html/man7/openssl-env.html]=man7/openssl-env.pod
GENERATE[html/man7/openssl-env.html]=man7/openssl-env.pod
DEPEND[man/man7/openssl-env.7]=man7/openssl-env.pod
GENERATE[man/man7/openssl-env.7]=man7/openssl-env.pod
DEPEND[html/man7/openssl-glossary.html]=man7/openssl-glossary.pod
GENERATE[html/man7/openssl-glossary.html]=man7/openssl-glossary.pod
DEPEND[man/man7/openssl-glossary.7]=man7/openssl-glossary.pod
GENERATE[man/man7/openssl-glossary.7]=man7/openssl-glossary.pod
DEPEND[html/man7/openssl-threads.html]=man7/openssl-threads.pod
GENERATE[html/man7/openssl-threads.html]=man7/openssl-threads.pod
DEPEND[man/man7/openssl-threads.7]=man7/openssl-threads.pod
GENERATE[man/man7/openssl-threads.7]=man7/openssl-threads.pod
DEPEND[html/man7/openssl_user_macros.html]=man7/openssl_user_macros.pod
GENERATE[html/man7/openssl_user_macros.html]=man7/openssl_user_macros.pod
DEPEND[man/man7/openssl_user_macros.7]=man7/openssl_user_macros.pod
GENERATE[man/man7/openssl_user_macros.7]=man7/openssl_user_macros.pod
DEPEND[man7/openssl_user_macros.pod]{pod}=man7/openssl_user_macros.pod.in
GENERATE[man7/openssl_user_macros.pod]=man7/openssl_user_macros.pod.in
DEPEND[html/man7/ossl_store-file.html]=man7/ossl_store-file.pod
GENERATE[html/man7/ossl_store-file.html]=man7/ossl_store-file.pod
DEPEND[man/man7/ossl_store-file.7]=man7/ossl_store-file.pod
GENERATE[man/man7/ossl_store-file.7]=man7/ossl_store-file.pod
DEPEND[html/man7/ossl_store.html]=man7/ossl_store.pod
GENERATE[html/man7/ossl_store.html]=man7/ossl_store.pod
DEPEND[man/man7/ossl_store.7]=man7/ossl_store.pod
GENERATE[man/man7/ossl_store.7]=man7/ossl_store.pod
DEPEND[html/man7/passphrase-encoding.html]=man7/passphrase-encoding.pod
GENERATE[html/man7/passphrase-encoding.html]=man7/passphrase-encoding.pod
DEPEND[man/man7/passphrase-encoding.7]=man7/passphrase-encoding.pod
GENERATE[man/man7/passphrase-encoding.7]=man7/passphrase-encoding.pod
DEPEND[html/man7/property.html]=man7/property.pod
GENERATE[html/man7/property.html]=man7/property.pod
DEPEND[man/man7/property.7]=man7/property.pod
GENERATE[man/man7/property.7]=man7/property.pod
DEPEND[html/man7/provider-asym_cipher.html]=man7/provider-asym_cipher.pod
GENERATE[html/man7/provider-asym_cipher.html]=man7/provider-asym_cipher.pod
DEPEND[man/man7/provider-asym_cipher.7]=man7/provider-asym_cipher.pod
GENERATE[man/man7/provider-asym_cipher.7]=man7/provider-asym_cipher.pod
DEPEND[html/man7/provider-base.html]=man7/provider-base.pod
GENERATE[html/man7/provider-base.html]=man7/provider-base.pod
DEPEND[man/man7/provider-base.7]=man7/provider-base.pod
GENERATE[man/man7/provider-base.7]=man7/provider-base.pod
DEPEND[html/man7/provider-cipher.html]=man7/provider-cipher.pod
GENERATE[html/man7/provider-cipher.html]=man7/provider-cipher.pod
DEPEND[man/man7/provider-cipher.7]=man7/provider-cipher.pod
GENERATE[man/man7/provider-cipher.7]=man7/provider-cipher.pod
DEPEND[html/man7/provider-decoder.html]=man7/provider-decoder.pod
GENERATE[html/man7/provider-decoder.html]=man7/provider-decoder.pod
DEPEND[man/man7/provider-decoder.7]=man7/provider-decoder.pod
GENERATE[man/man7/provider-decoder.7]=man7/provider-decoder.pod
DEPEND[html/man7/provider-digest.html]=man7/provider-digest.pod
GENERATE[html/man7/provider-digest.html]=man7/provider-digest.pod
DEPEND[man/man7/provider-digest.7]=man7/provider-digest.pod
GENERATE[man/man7/provider-digest.7]=man7/provider-digest.pod
DEPEND[html/man7/provider-encoder.html]=man7/provider-encoder.pod
GENERATE[html/man7/provider-encoder.html]=man7/provider-encoder.pod
DEPEND[man/man7/provider-encoder.7]=man7/provider-encoder.pod
GENERATE[man/man7/provider-encoder.7]=man7/provider-encoder.pod
DEPEND[html/man7/provider-kdf.html]=man7/provider-kdf.pod
GENERATE[html/man7/provider-kdf.html]=man7/provider-kdf.pod
DEPEND[man/man7/provider-kdf.7]=man7/provider-kdf.pod
GENERATE[man/man7/provider-kdf.7]=man7/provider-kdf.pod
DEPEND[html/man7/provider-kem.html]=man7/provider-kem.pod
GENERATE[html/man7/provider-kem.html]=man7/provider-kem.pod
DEPEND[man/man7/provider-kem.7]=man7/provider-kem.pod
GENERATE[man/man7/provider-kem.7]=man7/provider-kem.pod
DEPEND[html/man7/provider-keyexch.html]=man7/provider-keyexch.pod
GENERATE[html/man7/provider-keyexch.html]=man7/provider-keyexch.pod
DEPEND[man/man7/provider-keyexch.7]=man7/provider-keyexch.pod
GENERATE[man/man7/provider-keyexch.7]=man7/provider-keyexch.pod
DEPEND[html/man7/provider-keymgmt.html]=man7/provider-keymgmt.pod
GENERATE[html/man7/provider-keymgmt.html]=man7/provider-keymgmt.pod
DEPEND[man/man7/provider-keymgmt.7]=man7/provider-keymgmt.pod
GENERATE[man/man7/provider-keymgmt.7]=man7/provider-keymgmt.pod
DEPEND[html/man7/provider-mac.html]=man7/provider-mac.pod
GENERATE[html/man7/provider-mac.html]=man7/provider-mac.pod
DEPEND[man/man7/provider-mac.7]=man7/provider-mac.pod
GENERATE[man/man7/provider-mac.7]=man7/provider-mac.pod
DEPEND[html/man7/provider-object.html]=man7/provider-object.pod
GENERATE[html/man7/provider-object.html]=man7/provider-object.pod
DEPEND[man/man7/provider-object.7]=man7/provider-object.pod
GENERATE[man/man7/provider-object.7]=man7/provider-object.pod
DEPEND[html/man7/provider-rand.html]=man7/provider-rand.pod
GENERATE[html/man7/provider-rand.html]=man7/provider-rand.pod
DEPEND[man/man7/provider-rand.7]=man7/provider-rand.pod
GENERATE[man/man7/provider-rand.7]=man7/provider-rand.pod
DEPEND[html/man7/provider-signature.html]=man7/provider-signature.pod
GENERATE[html/man7/provider-signature.html]=man7/provider-signature.pod
DEPEND[man/man7/provider-signature.7]=man7/provider-signature.pod
GENERATE[man/man7/provider-signature.7]=man7/provider-signature.pod
DEPEND[html/man7/provider-storemgmt.html]=man7/provider-storemgmt.pod
GENERATE[html/man7/provider-storemgmt.html]=man7/provider-storemgmt.pod
DEPEND[man/man7/provider-storemgmt.7]=man7/provider-storemgmt.pod
GENERATE[man/man7/provider-storemgmt.7]=man7/provider-storemgmt.pod
DEPEND[html/man7/provider.html]=man7/provider.pod
GENERATE[html/man7/provider.html]=man7/provider.pod
DEPEND[man/man7/provider.7]=man7/provider.pod
GENERATE[man/man7/provider.7]=man7/provider.pod
DEPEND[html/man7/proxy-certificates.html]=man7/proxy-certificates.pod
GENERATE[html/man7/proxy-certificates.html]=man7/proxy-certificates.pod
DEPEND[man/man7/proxy-certificates.7]=man7/proxy-certificates.pod
GENERATE[man/man7/proxy-certificates.7]=man7/proxy-certificates.pod
DEPEND[html/man7/ssl.html]=man7/ssl.pod
GENERATE[html/man7/ssl.html]=man7/ssl.pod
DEPEND[man/man7/ssl.7]=man7/ssl.pod
GENERATE[man/man7/ssl.7]=man7/ssl.pod
DEPEND[html/man7/x509.html]=man7/x509.pod
GENERATE[html/man7/x509.html]=man7/x509.pod
DEPEND[man/man7/x509.7]=man7/x509.pod
GENERATE[man/man7/x509.7]=man7/x509.pod
IMAGEDOCS[man7]=man7/img/cipher.png \
man7/img/digest.png \
man7/img/kdf.png \
man7/img/mac.png \
man7/img/pkey.png \
man7/img/rand.png
HTMLDOCS[man7]=html/man7/EVP_ASYM_CIPHER-RSA.html \
html/man7/EVP_ASYM_CIPHER-SM2.html \
html/man7/EVP_CIPHER-AES.html \
html/man7/EVP_CIPHER-ARIA.html \
html/man7/EVP_CIPHER-BLOWFISH.html \
html/man7/EVP_CIPHER-CAMELLIA.html \
html/man7/EVP_CIPHER-CAST.html \
html/man7/EVP_CIPHER-CHACHA.html \
html/man7/EVP_CIPHER-DES.html \
html/man7/EVP_CIPHER-IDEA.html \
+html/man7/EVP_CIPHER-NULL.html \
html/man7/EVP_CIPHER-RC2.html \
html/man7/EVP_CIPHER-RC4.html \
html/man7/EVP_CIPHER-RC5.html \
html/man7/EVP_CIPHER-SEED.html \
html/man7/EVP_CIPHER-SM4.html \
html/man7/EVP_KDF-HKDF.html \
html/man7/EVP_KDF-KB.html \
html/man7/EVP_KDF-KRB5KDF.html \
html/man7/EVP_KDF-PBKDF1.html \
html/man7/EVP_KDF-PBKDF2.html \
html/man7/EVP_KDF-PKCS12KDF.html \
html/man7/EVP_KDF-SCRYPT.html \
html/man7/EVP_KDF-SS.html \
html/man7/EVP_KDF-SSHKDF.html \
html/man7/EVP_KDF-TLS13_KDF.html \
html/man7/EVP_KDF-TLS1_PRF.html \
html/man7/EVP_KDF-X942-ASN1.html \
html/man7/EVP_KDF-X942-CONCAT.html \
html/man7/EVP_KDF-X963.html \
html/man7/EVP_KEM-RSA.html \
html/man7/EVP_KEYEXCH-DH.html \
html/man7/EVP_KEYEXCH-ECDH.html \
html/man7/EVP_KEYEXCH-X25519.html \
html/man7/EVP_MAC-BLAKE2.html \
html/man7/EVP_MAC-CMAC.html \
html/man7/EVP_MAC-GMAC.html \
html/man7/EVP_MAC-HMAC.html \
html/man7/EVP_MAC-KMAC.html \
html/man7/EVP_MAC-Poly1305.html \
html/man7/EVP_MAC-Siphash.html \
html/man7/EVP_MD-BLAKE2.html \
html/man7/EVP_MD-MD2.html \
html/man7/EVP_MD-MD4.html \
html/man7/EVP_MD-MD5-SHA1.html \
html/man7/EVP_MD-MD5.html \
html/man7/EVP_MD-MDC2.html \
+html/man7/EVP_MD-NULL.html \
html/man7/EVP_MD-RIPEMD160.html \
html/man7/EVP_MD-SHA1.html \
html/man7/EVP_MD-SHA2.html \
html/man7/EVP_MD-SHA3.html \
html/man7/EVP_MD-SHAKE.html \
html/man7/EVP_MD-SM3.html \
html/man7/EVP_MD-WHIRLPOOL.html \
html/man7/EVP_MD-common.html \
html/man7/EVP_PKEY-DH.html \
html/man7/EVP_PKEY-DSA.html \
html/man7/EVP_PKEY-EC.html \
html/man7/EVP_PKEY-FFC.html \
html/man7/EVP_PKEY-HMAC.html \
html/man7/EVP_PKEY-RSA.html \
html/man7/EVP_PKEY-SM2.html \
html/man7/EVP_PKEY-X25519.html \
html/man7/EVP_RAND-CTR-DRBG.html \
html/man7/EVP_RAND-HASH-DRBG.html \
html/man7/EVP_RAND-HMAC-DRBG.html \
html/man7/EVP_RAND-SEED-SRC.html \
html/man7/EVP_RAND-TEST-RAND.html \
html/man7/EVP_RAND.html \
html/man7/EVP_SIGNATURE-DSA.html \
html/man7/EVP_SIGNATURE-ECDSA.html \
html/man7/EVP_SIGNATURE-ED25519.html \
html/man7/EVP_SIGNATURE-HMAC.html \
html/man7/EVP_SIGNATURE-RSA.html \
html/man7/OSSL_PROVIDER-FIPS.html \
html/man7/OSSL_PROVIDER-base.html \
html/man7/OSSL_PROVIDER-default.html \
html/man7/OSSL_PROVIDER-legacy.html \
html/man7/OSSL_PROVIDER-null.html \
html/man7/RAND.html \
html/man7/RSA-PSS.html \
html/man7/X25519.html \
html/man7/bio.html \
html/man7/crypto.html \
html/man7/ct.html \
html/man7/des_modes.html \
html/man7/evp.html \
html/man7/fips_module.html \
html/man7/life_cycle-cipher.html \
html/man7/life_cycle-digest.html \
html/man7/life_cycle-kdf.html \
html/man7/life_cycle-mac.html \
html/man7/life_cycle-pkey.html \
html/man7/life_cycle-rand.html \
html/man7/migration_guide.html \
html/man7/openssl-core.h.html \
html/man7/openssl-core_dispatch.h.html \
html/man7/openssl-core_names.h.html \
html/man7/openssl-env.html \
html/man7/openssl-glossary.html \
html/man7/openssl-threads.html \
html/man7/openssl_user_macros.html \
html/man7/ossl_store-file.html \
html/man7/ossl_store.html \
html/man7/passphrase-encoding.html \
html/man7/property.html \
html/man7/provider-asym_cipher.html \
html/man7/provider-base.html \
html/man7/provider-cipher.html \
html/man7/provider-decoder.html \
html/man7/provider-digest.html \
html/man7/provider-encoder.html \
html/man7/provider-kdf.html \
html/man7/provider-kem.html \
html/man7/provider-keyexch.html \
html/man7/provider-keymgmt.html \
html/man7/provider-mac.html \
html/man7/provider-object.html \
html/man7/provider-rand.html \
html/man7/provider-signature.html \
html/man7/provider-storemgmt.html \
html/man7/provider.html \
html/man7/proxy-certificates.html \
html/man7/ssl.html \
html/man7/x509.html
MANDOCS[man7]=man/man7/EVP_ASYM_CIPHER-RSA.7 \
man/man7/EVP_ASYM_CIPHER-SM2.7 \
man/man7/EVP_CIPHER-AES.7 \
man/man7/EVP_CIPHER-ARIA.7 \
man/man7/EVP_CIPHER-BLOWFISH.7 \
man/man7/EVP_CIPHER-CAMELLIA.7 \
man/man7/EVP_CIPHER-CAST.7 \
man/man7/EVP_CIPHER-CHACHA.7 \
man/man7/EVP_CIPHER-DES.7 \
man/man7/EVP_CIPHER-IDEA.7 \
+man/man7/EVP_CIPHER-NULL.7 \
man/man7/EVP_CIPHER-RC2.7 \
man/man7/EVP_CIPHER-RC4.7 \
man/man7/EVP_CIPHER-RC5.7 \
man/man7/EVP_CIPHER-SEED.7 \
man/man7/EVP_CIPHER-SM4.7 \
man/man7/EVP_KDF-HKDF.7 \
man/man7/EVP_KDF-KB.7 \
man/man7/EVP_KDF-KRB5KDF.7 \
man/man7/EVP_KDF-PBKDF1.7 \
man/man7/EVP_KDF-PBKDF2.7 \
man/man7/EVP_KDF-PKCS12KDF.7 \
man/man7/EVP_KDF-SCRYPT.7 \
man/man7/EVP_KDF-SS.7 \
man/man7/EVP_KDF-SSHKDF.7 \
man/man7/EVP_KDF-TLS13_KDF.7 \
man/man7/EVP_KDF-TLS1_PRF.7 \
man/man7/EVP_KDF-X942-ASN1.7 \
man/man7/EVP_KDF-X942-CONCAT.7 \
man/man7/EVP_KDF-X963.7 \
man/man7/EVP_KEM-RSA.7 \
man/man7/EVP_KEYEXCH-DH.7 \
man/man7/EVP_KEYEXCH-ECDH.7 \
man/man7/EVP_KEYEXCH-X25519.7 \
man/man7/EVP_MAC-BLAKE2.7 \
man/man7/EVP_MAC-CMAC.7 \
man/man7/EVP_MAC-GMAC.7 \
man/man7/EVP_MAC-HMAC.7 \
man/man7/EVP_MAC-KMAC.7 \
man/man7/EVP_MAC-Poly1305.7 \
man/man7/EVP_MAC-Siphash.7 \
man/man7/EVP_MD-BLAKE2.7 \
man/man7/EVP_MD-MD2.7 \
man/man7/EVP_MD-MD4.7 \
man/man7/EVP_MD-MD5-SHA1.7 \
man/man7/EVP_MD-MD5.7 \
man/man7/EVP_MD-MDC2.7 \
+man/man7/EVP_MD-NULL.7 \
man/man7/EVP_MD-RIPEMD160.7 \
man/man7/EVP_MD-SHA1.7 \
man/man7/EVP_MD-SHA2.7 \
man/man7/EVP_MD-SHA3.7 \
man/man7/EVP_MD-SHAKE.7 \
man/man7/EVP_MD-SM3.7 \
man/man7/EVP_MD-WHIRLPOOL.7 \
man/man7/EVP_MD-common.7 \
man/man7/EVP_PKEY-DH.7 \
man/man7/EVP_PKEY-DSA.7 \
man/man7/EVP_PKEY-EC.7 \
man/man7/EVP_PKEY-FFC.7 \
man/man7/EVP_PKEY-HMAC.7 \
man/man7/EVP_PKEY-RSA.7 \
man/man7/EVP_PKEY-SM2.7 \
man/man7/EVP_PKEY-X25519.7 \
man/man7/EVP_RAND-CTR-DRBG.7 \
man/man7/EVP_RAND-HASH-DRBG.7 \
man/man7/EVP_RAND-HMAC-DRBG.7 \
man/man7/EVP_RAND-SEED-SRC.7 \
man/man7/EVP_RAND-TEST-RAND.7 \
man/man7/EVP_RAND.7 \
man/man7/EVP_SIGNATURE-DSA.7 \
man/man7/EVP_SIGNATURE-ECDSA.7 \
man/man7/EVP_SIGNATURE-ED25519.7 \
man/man7/EVP_SIGNATURE-HMAC.7 \
man/man7/EVP_SIGNATURE-RSA.7 \
man/man7/OSSL_PROVIDER-FIPS.7 \
man/man7/OSSL_PROVIDER-base.7 \
man/man7/OSSL_PROVIDER-default.7 \
man/man7/OSSL_PROVIDER-legacy.7 \
man/man7/OSSL_PROVIDER-null.7 \
man/man7/RAND.7 \
man/man7/RSA-PSS.7 \
man/man7/X25519.7 \
man/man7/bio.7 \
man/man7/crypto.7 \
man/man7/ct.7 \
man/man7/des_modes.7 \
man/man7/evp.7 \
man/man7/fips_module.7 \
man/man7/life_cycle-cipher.7 \
man/man7/life_cycle-digest.7 \
man/man7/life_cycle-kdf.7 \
man/man7/life_cycle-mac.7 \
man/man7/life_cycle-pkey.7 \
man/man7/life_cycle-rand.7 \
man/man7/migration_guide.7 \
man/man7/openssl-core.h.7 \
man/man7/openssl-core_dispatch.h.7 \
man/man7/openssl-core_names.h.7 \
man/man7/openssl-env.7 \
man/man7/openssl-glossary.7 \
man/man7/openssl-threads.7 \
man/man7/openssl_user_macros.7 \
man/man7/ossl_store-file.7 \
man/man7/ossl_store.7 \
man/man7/passphrase-encoding.7 \
man/man7/property.7 \
man/man7/provider-asym_cipher.7 \
man/man7/provider-base.7 \
man/man7/provider-cipher.7 \
man/man7/provider-decoder.7 \
man/man7/provider-digest.7 \
man/man7/provider-encoder.7 \
man/man7/provider-kdf.7 \
man/man7/provider-kem.7 \
man/man7/provider-keyexch.7 \
man/man7/provider-keymgmt.7 \
man/man7/provider-mac.7 \
man/man7/provider-object.7 \
man/man7/provider-rand.7 \
man/man7/provider-signature.7 \
man/man7/provider-storemgmt.7 \
man/man7/provider.7 \
man/man7/proxy-certificates.7 \
man/man7/ssl.7 \
man/man7/x509.7
diff --git a/doc/fingerprints.txt b/doc/fingerprints.txt
index 4f95f2beaec8..9a26f7c66722 100644
--- a/doc/fingerprints.txt
+++ b/doc/fingerprints.txt
@@ -1,25 +1,28 @@
Fingerprints for Signing Releases
OpenSSL releases are signed with PGP/GnuPG keys. This file contains
the fingerprints of team members who are "authorized" to sign the
next release.
The signature is a detached cleartxt signature, with the same name
as the release but with ".asc" appended. For example, release
1.0.1h can be found in openssl-1.0.1h.tar.gz with the signature
in the file named openssl-1.0.1h.tar.gz.asc.
The following is the list of fingerprints for the keys that are
currently in use to sign OpenSSL distributions:
+OpenSSL OMC:
+EFC0 A467 D613 CB83 C7ED 6D30 D894 E2CE 8B3D 79F5
+
Richard Levitte:
7953 AC1F BC3D C8B3 B292 393E D5E9 E43F 7DF9 EE8C
Matt Caswell:
8657 ABB2 60F0 56B1 E519 0839 D9C4 D26D 0E60 4491
Paul Dale:
B7C1 C143 60F3 53A3 6862 E4D5 231C 84CD DCC6 9C45
Tomáš Mráz:
A21F AB74 B008 8AA3 6115 2586 B8EF 1A6B A9DA 2D5C
diff --git a/doc/internal/man3/ossl_cmp_certreq_new.pod b/doc/internal/man3/ossl_cmp_certreq_new.pod
index 068e1b29b977..37a234066d36 100644
--- a/doc/internal/man3/ossl_cmp_certreq_new.pod
+++ b/doc/internal/man3/ossl_cmp_certreq_new.pod
@@ -1,177 +1,178 @@
=pod
=head1 NAME
ossl_cmp_certreq_new,
ossl_cmp_certrep_new,
ossl_cmp_rr_new,
ossl_cmp_rp_new,
ossl_cmp_certConf_new,
ossl_cmp_pkiconf_new,
ossl_cmp_pollReq_new,
ossl_cmp_pollRep_new,
ossl_cmp_genm_new,
ossl_cmp_genp_new,
ossl_cmp_error_new
- functions for generating CMP messages
=head1 SYNOPSIS
#include "cmp_local.h"
OSSL_ossl_cmp_MSG *ossl_cmp_certreq_new(OSSL_CMP_CTX *ctx, int bodytype,
const OSSL_CRMF_MSG *crm);
OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
int certReqId, const OSSL_CMP_PKISI *si,
X509 *cert, const X509 *encryption_recip,
STACK_OF(X509) *chain, STACK_OF(X509) *caPubs,
int unprotectedErrors);
OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
const OSSL_CRMF_CERTID *cid,
int unprotectedErrors);
- OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
- const char *text);
+ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int certReqId,
+ int fail_info, const char *text);
OSSL_CMP_MSG *ossl_cmp_pkiconf_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_pollReq_new(OSSL_CMP_CTX *ctx, int crid);
OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid, int poll_after);
OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
int64_t errorCode, const char *details,
int unprotected);
=head1 DESCRIPTION
This is the internal API for creating various CMP PKIMESSAGES.
All functions are based on L<ossl_cmp_msg_create(3)>.
The allocate a new message, fill it with the relevant data derived from
the given B<OSSL_CMP_CTX>, and create the applicable protection.
ossl_cmp_certreq_new() creates a PKIMessage for requesting a certificate,
which can be either of IR/CR/KUR/P10CR, depending on the given I<bodytype>.
The CRMF message to use may be given explicitly via a non-NULL I<crm> argument,
otherwise it is created from the information in the I<ctx>.
Available CMP certificate request PKIMessage I<bodytype>s are:
=over 4
=item * B<OSSL_CMP_PKIBODY_IR> - Initialization Request
=item * B<OSSL_CMP_PKIBODY_CR> - Certification Request
=item * B<OSSL_CMP_PKIBODY_P10CR> - PKCS#10 Certification Request
=item * B<OSSL_CMP_PKIBODY_KUR> - Key Update Request
=back
ossl_cmp_certrep_new() creates a PKIMessage for certificate response,
which can be either of IP/CP/KUP, depending on the given I<bodytype>,
with the given I<certReqId> and I<si> values and optionally with I<cert>,
I<chain>, and I<caPubs>. The I<cert>, I<chain>, and I<caPubs> arguments
are not consumed if present but their internal reference counter is increased.
The I<encryption_recip> is currently unsupported.
The function does not protect the message if the B<status> value in I<si>
is B<rejected> and I<unprotectedErrors> is nonzero.
Available CMP certificate response PKIMessage I<bodytype>s are:
=over 4
=item * B<OSSL_CMP_PKIBODY_IP> - Initialization Response
=item * B<OSSL_CMP_PKIBODY_CP> - Certification Response
=item * B<OSSL_CMP_PKIBODY_KUP> - Key Update Response
=back
The list of all CMP PKIMessage I<bodytype>s is:
#define OSSL_CMP_PKIBODY_IR 0
#define OSSL_CMP_PKIBODY_IP 1
#define OSSL_CMP_PKIBODY_CR 2
#define OSSL_CMP_PKIBODY_CP 3
#define OSSL_CMP_PKIBODY_P10CR 4
#define OSSL_CMP_PKIBODY_POPDECC 5
#define OSSL_CMP_PKIBODY_POPDECR 6
#define OSSL_CMP_PKIBODY_KRR 9
#define OSSL_CMP_PKIBODY_KRP 10
#define OSSL_CMP_PKIBODY_RR 11
#define OSSL_CMP_PKIBODY_RP 12
#define OSSL_CMP_PKIBODY_CCR 13
#define OSSL_CMP_PKIBODY_CCP 14
#define OSSL_CMP_PKIBODY_CKUANN 15
#define OSSL_CMP_PKIBODY_CANN 16
#define OSSL_CMP_PKIBODY_RANN 17
#define OSSL_CMP_PKIBODY_CRLANN 18
#define OSSL_CMP_PKIBODY_PKICONF 19
#define OSSL_CMP_PKIBODY_NESTED 20
#define OSSL_CMP_PKIBODY_GENM 21
#define OSSL_CMP_PKIBODY_GENP 22
#define OSSL_CMP_PKIBODY_ERROR 23
#define OSSL_CMP_PKIBODY_CERTCONF 24
#define OSSL_CMP_PKIBODY_POLLREQ 25
#define OSSL_CMP_PKIBODY_POLLREP 26
ossl_cmp_rr_new() creates a Revocation Request message from the
information set via OSSL_CMP_CTX_set1_oldClCert().
ossl_cmp_rp_new() creates a Revocation Response message with I<si> and I<cid>.
It does not protect the message if the B<status> value in I<si> is B<rejected>
and I<unprotectedErrors> is nonzero.
ossl_cmp_certConf_new() creates a Certificate Confirmation message for the last
-received certificate. PKIStatus defaults to B<accepted> if the I<fail_info> bit
-field is 0. Else it is taken as the failInfo of the PKIStatusInfo, PKIStatus is
+received certificate with the given I<certReqId>.
+The PKIStatus defaults to B<accepted> if the I<fail_info> bit field is 0.
+Otherwise it is taken as the failInfo of the PKIStatusInfo, PKIStatus is
set to B<rejected>, and I<text> is copied to statusString unless it is NULL.
ossl_cmp_pkiconf_new() creates a PKI Confirmation message.
ossl_cmp_pollReq_new() creates a Polling Request message with certReqId set to
I<crid>.
ossl_cmp_pollRep_new() creates a Polling Response message with certReqId set to
I<crid> and pollAfter to I<poll_after>.
ossl_cmp_genm_new() creates a new General Message with an empty ITAV stack.
ossl_cmp_genp_new() creates a new General Response with an empty ITAV stack.
ossl_cmp_error_new() creates a new Error Message with the given contents
I<si>, I<errorCode>, and optional I<details>.
If I<errorCode> is positive and in the range of an OpenSSL error code,
the library and reason strings are included in the B<errorDetails> field.
If given, the I<details> are added to the contents of the B<errorDetails> field.
The function does not protect the message if I<unprotectedErrors> is nonzero.
=head1 NOTES
CMP is specified in RFC 4210 (and CRMF in RFC 4211).
=head1 RETURN VALUES
All of the functions return a new OSSL_CMP_MSG structure containing
the generated message on success, or NULL on error.
=head1 SEE ALSO
L<ossl_cmp_msg_create(3)>,
L<OSSL_CMP_CTX_new(3)>, L<ERR_load_strings(3)>
=head1 HISTORY
The OpenSSL CMP support was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/internal/man3/ossl_cmp_mock_srv_new.pod b/doc/internal/man3/ossl_cmp_mock_srv_new.pod
index 837ca06bb34c..7bc449a84352 100644
--- a/doc/internal/man3/ossl_cmp_mock_srv_new.pod
+++ b/doc/internal/man3/ossl_cmp_mock_srv_new.pod
@@ -1,87 +1,89 @@
=pod
=head1 NAME
ossl_cmp_mock_srv_new,
ossl_cmp_mock_srv_free,
ossl_cmp_mock_srv_set1_certOut,
ossl_cmp_mock_srv_set1_chainOut,
ossl_cmp_mock_srv_set1_caPubsOut,
ossl_cmp_mock_srv_set_statusInfo,
-ossl_cmp_mock_srv_set_send_error,
+ossl_cmp_mock_srv_set_sendError,
ossl_cmp_mock_srv_set_pollCount,
ossl_cmp_mock_srv_set_checkAfterTime
- functions used for testing with CMP mock server
=head1 SYNOPSIS
#include "apps/cmp_mock_srv.h"
OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq);
void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx);
int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
STACK_OF(X509) *chain);
int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
STACK_OF(X509) *caPubs);
int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
int fail_info, const char *text);
- int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val);
+ int ossl_cmp_mock_srv_set_sendError(OSSL_CMP_SRV_CTX *srv_ctx, int bodytype);
int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count);
int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec);
=head1 DESCRIPTION
ossl_cmp_mock_srv_new() allocates the contexts for the CMP mock server
associated with the library context I<libctx> and property query string
I<propq>, both of which may be NULL to select the defaults.
ossl_cmp_mock_srv_free() deallocates the contexts for the CMP mock server.
-OSSL_CMP_SRV_CTX_set1_certOut() sets the certificate to be returned in
+ossl_cmp_mock_srv_set1_certOut() sets the certificate to be returned in
cp/ip/kup.
-OSSL_CMP_SRV_CTX_set1_chainOut() sets the certificate chain to be added to
+ossl_cmp_mock_srv_set1_chainOut() sets the certificate chain to be added to
the extraCerts in a cp/ip/kup.
-It should to useful to validate B<certOut>.
+It should be useful for the validation of the certificate given via
+ossl_cmp_mock_srv_set1_certOut().
-OSSL_CMP_SRV_CTX_set1_caPubsOut() sets the caPubs to be returned in an ip.
+ossl_cmp_mock_srv_set1_caPubsOut() sets the caPubs to be returned in an ip.
-OSSL_CMP_SRV_CTX_set_statusInfo() sets the status info to be returned.
+ossl_cmp_mock_srv_set_statusInfo() sets the status info to be returned.
-OSSL_CMP_SRV_CTX_set_send_error() enables enforcement of error responses.
+ossl_cmp_mock_srv_set_sendError() enables enforcement of error responses
+for requests of the given I<bodytype>, or for all requests if I<bodytype> is 1.
+A I<bodytype> of -1 can be used to disable this feature, which is the default.
-OSSL_CMP_SRV_CTX_set_pollCount() sets the number of polls before cert response.
+ossl_cmp_mock_srv_set_pollCount() sets the number of polls before cert response.
-OSSL_CMP_SRV_CTX_set_checkAfterTime() sets the number of seconds
+ossl_cmp_mock_srv_set_checkAfterTime() sets the number of seconds
the client should wait for the next poll.
-
=head1 NOTES
CMP is defined in RFC 4210 (and CRMF in RFC 4211).
=head1 RETURN VALUES
ossl_cmp_mock_srv() returns a B<OSSL_CMP_SRV_CTX> structure on success,
NULL on error.
ossl_cmp_mock_srv_free() does not return a value.
All other functions return 1 on success, 0 on error.
=head1 HISTORY
The OpenSSL CMP support was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/internal/man3/ossl_cmp_msg_protect.pod b/doc/internal/man3/ossl_cmp_msg_protect.pod
index ae7771280763..744fbce576ca 100644
--- a/doc/internal/man3/ossl_cmp_msg_protect.pod
+++ b/doc/internal/man3/ossl_cmp_msg_protect.pod
@@ -1,62 +1,66 @@
=pod
=head1 NAME
ossl_cmp_calc_protection,
ossl_cmp_msg_protect,
ossl_cmp_msg_add_extraCerts
- functions for producing CMP message protection
=head1 SYNOPSIS
#include "cmp_local.h"
ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *msg);
int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
=head1 DESCRIPTION
ossl_cmp_calc_protection() calculates the protection for the given I<msg>
according to the algorithm and parameters in the message header's protectionAlg
using the credentials, library context, and property criteria in the I<ctx>.
ossl_cmp_msg_protect() (re-)protects the given message I<msg> using an algorithm
depending on the available context information given in the I<ctx>.
If there is a secretValue it selects PBMAC, else if there is a protection cert
-it selects Signature and uses L<ossl_cmp_msg_add_extraCerts(3)>.
+it selects Signature and uses ossl_cmp_msg_add_extraCerts (see below).
It also sets the protectionAlg field in the message header accordingly.
ossl_cmp_msg_add_extraCerts() adds elements to the extraCerts field in I<msg>.
If signature-based message protection is used it adds first the CMP signer cert
ctx->cert and then its chain ctx->chain. If this chain is not present in I<ctx>
tries to build it using ctx->untrusted and caches the result in ctx->chain.
In any case all the certificates explicitly specified to be sent out (i.e.,
I<ctx->extraCertsOut>) are added. Note that it will NOT add the root certificate
of the chain, i.e, the trust anchor (unless it is part of extraCertsOut).
=head1 NOTES
CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+The I<ctx> parameter of ossl_cmp_msg_add_extraCerts()
+and thus also of ossl_cmp_msg_protect() cannot be made I<const>
+because I<ctx->chain> may get adapted to cache the chain of the CMP signer cert.
+
=head1 RETURN VALUES
ossl_cmp_calc_protection() returns the protection on success, else NULL.
All other functions return 1 on success, 0 on error.
=head1 HISTORY
The OpenSSL CMP support was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/internal/man3/ossl_cmp_pkisi_get_status.pod b/doc/internal/man3/ossl_cmp_pkisi_get_status.pod
index 21f6f90b39d3..e44bfd3f0190 100644
--- a/doc/internal/man3/ossl_cmp_pkisi_get_status.pod
+++ b/doc/internal/man3/ossl_cmp_pkisi_get_status.pod
@@ -1,99 +1,99 @@
=pod
=head1 NAME
ossl_cmp_certresponse_get1_cert,
ossl_cmp_pkisi_get_status,
ossl_cmp_PKIStatus_to_string,
ossl_cmp_pkisi_get0_statusString,
ossl_cmp_pkisi_get_pkifailureinfo,
ossl_cmp_pkisi_check_pkifailureinfo
- functions for managing PKI status information
=head1 SYNOPSIS
#include "cmp.h"
# define OSSL_CMP_PKIFAILUREINFO_badAlg 0
# define OSSL_CMP_PKIFAILUREINFO_badMessageCheck 1
# define OSSL_CMP_PKIFAILUREINFO_badRequest 2
# define OSSL_CMP_PKIFAILUREINFO_badTime 3
# define OSSL_CMP_PKIFAILUREINFO_badCertId 4
# define OSSL_CMP_PKIFAILUREINFO_badDataFormat 5
# define OSSL_CMP_PKIFAILUREINFO_wrongAuthority 6
# define OSSL_CMP_PKIFAILUREINFO_incorrectData 7
# define OSSL_CMP_PKIFAILUREINFO_missingTimeStamp 8
# define OSSL_CMP_PKIFAILUREINFO_badPOP 9
# define OSSL_CMP_PKIFAILUREINFO_certRevoked 10
# define OSSL_CMP_PKIFAILUREINFO_certConfirmed 11
# define OSSL_CMP_PKIFAILUREINFO_wrongIntegrity 12
# define OSSL_CMP_PKIFAILUREINFO_badRecipientNonce 13
# define OSSL_CMP_PKIFAILUREINFO_timeNotAvailable 14
# define OSSL_CMP_PKIFAILUREINFO_unacceptedPolicy 15
# define OSSL_CMP_PKIFAILUREINFO_unacceptedExtension 16
# define OSSL_CMP_PKIFAILUREINFO_addInfoNotAvailable 17
# define OSSL_CMP_PKIFAILUREINFO_badSenderNonce 18
# define OSSL_CMP_PKIFAILUREINFO_badCertTemplate 19
# define OSSL_CMP_PKIFAILUREINFO_signerNotTrusted 20
# define OSSL_CMP_PKIFAILUREINFO_transactionIdInUse 21
# define OSSL_CMP_PKIFAILUREINFO_unsupportedVersion 22
# define OSSL_CMP_PKIFAILUREINFO_notAuthorized 23
# define OSSL_CMP_PKIFAILUREINFO_systemUnavail 24
# define OSSL_CMP_PKIFAILUREINFO_systemFailure 25
# define OSSL_CMP_PKIFAILUREINFO_duplicateCertReq 26
# define OSSL_CMP_PKIFAILUREINFO_MAX 26
- X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CERTRESPONSE *crep,
- const OSSL_CMP_CTX *ctx, EVP_PKEY *pkey);
+ X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_CERTRESPONSE *crep);
int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si);
const char *ossl_cmp_PKIStatus_to_string(int status);
OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusString(const OSSL_CMP_PKISI *si);
int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si);
int ossl_cmp_pkisi_check_pkifailureinfo(const OSSL_CMP_PKISI *si, int index);
=head1 DESCRIPTION
ossl_cmp_certresponse_get1_cert() returns a pointer to a copy of the newly
enrolled certificate from the given certResponse I<crep>, or NULL on error.
-In case of indirect POPO uses data from the I<ctx> and the private key I<pkey>.
+Uses data from I<ctx>, which in case of indirect POPO includes the private key.
ossl_cmp_pkisi_get_status() returns the PKIStatus of I<si>, or -1 on error.
ossl_cmp_PKIStatus_to_string() returns a human-readable string representing
the PKIStatus values as specified in RFC 4210, Appendix F.
ossl_cmp_pkisi_get0_statusString() returns a direct pointer to the statusString
field contained in I<si>.
ossl_cmp_pkisi_get_pkifailureinfo() returns the PKIFailureInfo bits
of I<si>, encoded as integer, or -1 on error.
ossl_cmp_pkisi_check_pkifailureinfo() returns the state of the bit (0 or 1)
with index I<index> in the PKIFailureInfo of the I<si>, or -1 on error.
=head1 NOTES
CMP is defined in RFC 4210 (and CRMF in RFC 4211).
=head1 RETURN VALUES
See the individual functions above.
=head1 SEE ALSO
L<OSSL_CMP_CTX_new(3)>, L<ossl_cmp_certreq_new(3)>
=head1 HISTORY
The OpenSSL CMP support was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in
index 77e82091413b..4250deb426fc 100644
--- a/doc/man1/openssl-cmp.pod.in
+++ b/doc/man1/openssl-cmp.pod.in
@@ -1,1244 +1,1298 @@
=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 requested
-in Initialization Request (IR), Certification Request(CR), or
-Key Update Request (KUR).
+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
+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,
-while its public key is ignored if I<-newkey> is given.
-It may also be used with B<-cmd> I<rr> to specify the certificate to be revoked
+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
of the CMP server to connect to using HTTP(S).
-This excludes I<-port> and I<-use_mock_srv> and is ignored with I<-rspin>.
+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.
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>
-When validating signature-based protection of CMP response messages,
-these are the CA certificate(s) to trust while checking certificate chains
-during CMP server authentication.
-This option gives more flexibility than the B<-srvcert> option because the
-server-side CMP signer certificate is not pinned but may be any certificate
-for which a chain to one of the given trusted certificates can be constructed.
+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 no B<-trusted>, B<-srvcert>, and B<-secret> option is given
-then protected response messages from the server are not authenticated.
+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 CMP client certificate (to include in the extraCerts field of outgoing
-messages) and for the TLS client certificate (if TLS is enabled)
+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 the CMP server certificate (checking signature-based
+when validating server certificates (checking signature-based
CMP message protection) and when validating newly enrolled certificates.
-Multiple sources may be given, separated by commas and/or whitespace.
-Each file may contain multiple 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 validating signature-based protection of CMP response messages.
-May be set alternatively to the B<-trusted> option to pin the accepted server.
+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 incoming CMP messages.
+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,
-else C<digitalSignature> must be allowed for signer certificate.
+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>
Prefer PBM-based message protection with given source of a secret value.
The secret is used for creating PBM-based protection of outgoing messages
and (as far as needed) for validating PBM-based protection of incoming messages.
PBM stands for Password-Based Message Authentication Code.
This takes precedence over the B<-cert> and B<-key> options.
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.
+and as fallback issuer entry in the certificate template of IR/CR/KUR messages.
+
When using signature-based message protection, this "protection 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 PBM 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 MSG_MAC_ALG.
If applicable, this is used for message protection and
-Proof-of-Possession (POPO) signatures.
+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 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 messages without CMP-level protection.
+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)
-when connecting to CMP server via HTTP.
-This option is not supported with the I<-port> option
-and is ignored with the I<-use_mock_srv> and I<-rspin> options
-or if the I<-server> option is not given.
+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 sequence of CMP requests from file(s).
+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 "...").
-As many files are read as needed for a complete transaction.
+
+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 requires re-protecting them as far as they were protected before.
+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 sequence of CMP requests to file(s).
+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.
-As many files are written as needed to store the complete transaction.
+
+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 sequence of CMP responses provided in file(s), skipping server.
-This excludes I<-server>, I<-port>, and I<-use_mock_srv>.
+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.
-As many files are read as needed for the complete transaction.
+
+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 sequence of CMP responses to file(s).
+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.
-As many files are written as needed to store the complete transaction.
+
+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 I<-server>, I<-port>, and I<-rspin>.
+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 I<-server>, I<-rspin>, and I<-use_mock_srv>.
+This 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).
+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 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 with PBM-based protection 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 repated 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/doc/man1/openssl-enc.pod.in b/doc/man1/openssl-enc.pod.in
index fdfa7f67d3ee..e6d5103bd91a 100644
--- a/doc/man1/openssl-enc.pod.in
+++ b/doc/man1/openssl-enc.pod.in
@@ -1,458 +1,459 @@
=pod
{- OpenSSL::safe::output_do_not_edit_headers(); -}
=head1 NAME
openssl-enc - symmetric cipher routines
=head1 SYNOPSIS
B<openssl> B<enc>|I<cipher>
[B<-I<cipher>>]
[B<-help>]
[B<-list>]
[B<-ciphers>]
[B<-in> I<filename>]
[B<-out> I<filename>]
[B<-pass> I<arg>]
[B<-e>]
[B<-d>]
[B<-a>]
[B<-base64>]
[B<-A>]
[B<-k> I<password>]
[B<-kfile> I<filename>]
[B<-K> I<key>]
[B<-iv> I<IV>]
[B<-S> I<salt>]
[B<-salt>]
[B<-nosalt>]
[B<-z>]
[B<-md> I<digest>]
[B<-iter> I<count>]
[B<-pbkdf2>]
[B<-p>]
[B<-P>]
[B<-bufsize> I<number>]
[B<-nopad>]
[B<-v>]
[B<-debug>]
[B<-none>]
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_r_synopsis -}
{- $OpenSSL::safe::opt_provider_synopsis -}
B<openssl> I<cipher> [B<...>]
=head1 DESCRIPTION
The symmetric cipher commands allow data to be encrypted or decrypted
using various block and stream ciphers using keys based on passwords
or explicitly provided. Base64 encoding or decoding can also be performed
either by itself or in addition to the encryption or decryption.
=head1 OPTIONS
=over 4
=item B<-I<cipher>>
The cipher to use.
=item B<-help>
Print out a usage message.
=item B<-list>
List all supported ciphers.
=item B<-ciphers>
Alias of -list to display all supported ciphers.
=item B<-in> I<filename>
The input filename, standard input by default.
=item B<-out> I<filename>
The output filename, standard output by default.
=item B<-pass> I<arg>
The password source. For more information about the format of I<arg>
see L<openssl-passphrase-options(1)>.
=item B<-e>
Encrypt the input data: this is the default.
=item B<-d>
Decrypt the input data.
=item B<-a>
Base64 process the data. This means that if encryption is taking place
the data is base64 encoded after encryption. If decryption is set then
the input data is base64 decoded before being decrypted.
=item B<-base64>
Same as B<-a>
=item B<-A>
If the B<-a> option is set then base64 process the data on one line.
=item B<-k> I<password>
The password to derive the key from. This is for compatibility with previous
versions of OpenSSL. Superseded by the B<-pass> argument.
=item B<-kfile> I<filename>
Read the password to derive the key from the first line of I<filename>.
This is for compatibility with previous versions of OpenSSL. Superseded by
the B<-pass> argument.
=item B<-md> I<digest>
Use the specified digest to create the key from the passphrase.
The default algorithm is sha-256.
=item B<-iter> I<count>
Use a given number of iterations on the password in deriving the encryption key.
High values increase the time required to brute-force the resulting file.
This option enables the use of PBKDF2 algorithm to derive the key.
=item B<-pbkdf2>
-Use PBKDF2 algorithm with default iteration count unless otherwise specified.
+Use PBKDF2 algorithm with a default iteration count of 10000
+unless otherwise specified by the B<-iter> command line option.
=item B<-nosalt>
Don't use a salt in the key derivation routines. This option B<SHOULD NOT> be
used except for test purposes or compatibility with ancient versions of
OpenSSL.
=item B<-salt>
Use salt (randomly generated or provide with B<-S> option) when
encrypting, this is the default.
=item B<-S> I<salt>
The actual salt to use: this must be represented as a string of hex digits.
If this option is used while encrypting, the same exact value will be needed
again during decryption.
=item B<-K> I<key>
The actual key to use: this must be represented as a string comprised only
of hex digits. If only the key is specified, the IV must additionally specified
using the B<-iv> option. When both a key and a password are specified, the
key given with the B<-K> option will be used and the IV generated from the
password will be taken. It does not make much sense to specify both key
and password.
=item B<-iv> I<IV>
The actual IV to use: this must be represented as a string comprised only
of hex digits. When only the key is specified using the B<-K> option, the
IV must explicitly be defined. When a password is being specified using
one of the other options, the IV is generated from this password.
=item B<-p>
Print out the key and IV used.
=item B<-P>
Print out the key and IV used then immediately exit: don't do any encryption
or decryption.
=item B<-bufsize> I<number>
Set the buffer size for I/O.
=item B<-nopad>
Disable standard block padding.
=item B<-v>
Verbose print; display some statistics about I/O and buffer sizes.
=item B<-debug>
Debug the BIOs used for I/O.
=item B<-z>
Compress or decompress encrypted data using zlib after encryption or before
decryption. This option exists only if OpenSSL was compiled with the zlib
or zlib-dynamic option.
=item B<-none>
Use NULL cipher (no encryption or decryption of input).
{- $OpenSSL::safe::opt_r_item -}
{- $OpenSSL::safe::opt_provider_item -}
{- $OpenSSL::safe::opt_engine_item -}
=back
=head1 NOTES
The program can be called either as C<openssl I<cipher>> or
C<openssl enc -I<cipher>>. The first form doesn't work with
engine-provided ciphers, because this form is processed before the
configuration file is read and any ENGINEs loaded.
Use the L<openssl-list(1)> command to get a list of supported ciphers.
Engines which provide entirely new encryption algorithms (such as the ccgost
engine which provides gost89 algorithm) should be configured in the
configuration file. Engines specified on the command line using B<-engine>
option can only be used for hardware-assisted implementations of
ciphers which are supported by the OpenSSL core or another engine specified
in the configuration file.
When the enc command lists supported ciphers, ciphers provided by engines,
specified in the configuration files are listed too.
A password will be prompted for to derive the key and IV if necessary.
The B<-salt> option should B<ALWAYS> be used if the key is being derived
from a password unless you want compatibility with previous versions of
OpenSSL.
Without the B<-salt> option it is possible to perform efficient dictionary
attacks on the password and to attack stream cipher encrypted data. The reason
for this is that without the salt the same password always generates the same
encryption key.
When the salt is generated at random (that means when encrypting using a
passphrase without explicit salt given using B<-S> option), the first bytes
of the encrypted data are reserved to store the salt for later decrypting.
Some of the ciphers do not have large keys and others have security
implications if not used correctly. A beginner is advised to just use
a strong block cipher, such as AES, in CBC mode.
All the block ciphers normally use PKCS#5 padding, also known as standard
block padding. This allows a rudimentary integrity or password check to
be performed. However, since the chance of random data passing the test
is better than 1 in 256 it isn't a very good test.
If padding is disabled then the input data must be a multiple of the cipher
block length.
All RC2 ciphers have the same key and effective key length.
Blowfish and RC5 algorithms use a 128 bit key.
Please note that OpenSSL 3.0 changed the effect of the B<-S> option.
Any explicit salt value specified via this option is no longer prepended to the
ciphertext when encrypting, and must again be explicitly provided when decrypting.
Conversely, when the B<-S> option is used during decryption, the ciphertext
is expected to not have a prepended salt value.
When using OpenSSL 3.0 or later to decrypt data that was encrypted with an
explicit salt under OpenSSL 1.1.1 do not use the B<-S> option, the salt will
then be read from the ciphertext.
To generate ciphertext that can be decrypted with OpenSSL 1.1.1 do not use
the B<-S> option, the salt will be then be generated randomly and prepended
to the output.
=head1 SUPPORTED CIPHERS
Note that some of these ciphers can be disabled at compile time
and some are available only if an appropriate engine is configured
in the configuration file. The output when invoking this command
with the B<-list> option (that is C<openssl enc -list>) is
a list of ciphers, supported by your version of OpenSSL, including
ones provided by configured engines.
This command does not support authenticated encryption modes
like CCM and GCM, and will not support such modes in the future.
This is due to having to begin streaming output (e.g., to standard output
when B<-out> is not used) before the authentication tag could be validated.
When this command is used in a pipeline, the receiving end will not be
able to roll back upon authentication failure. The AEAD modes currently in
common use also suffer from catastrophic failure of confidentiality and/or
integrity upon reuse of key/iv/nonce, and since B<openssl enc> places the
entire burden of key/iv/nonce management upon the user, the risk of
exposing AEAD modes is too great to allow. These key/iv/nonce
management issues also affect other modes currently exposed in this command,
but the failure modes are less extreme in these cases, and the
functionality cannot be removed with a stable release branch.
For bulk encryption of data, whether using authenticated encryption
modes or other modes, L<openssl-cms(1)> is recommended, as it provides a
standard data format and performs the needed key/iv/nonce management.
base64 Base 64
bf-cbc Blowfish in CBC mode
bf Alias for bf-cbc
blowfish Alias for bf-cbc
bf-cfb Blowfish in CFB mode
bf-ecb Blowfish in ECB mode
bf-ofb Blowfish in OFB mode
cast-cbc CAST in CBC mode
cast Alias for cast-cbc
cast5-cbc CAST5 in CBC mode
cast5-cfb CAST5 in CFB mode
cast5-ecb CAST5 in ECB mode
cast5-ofb CAST5 in OFB mode
chacha20 ChaCha20 algorithm
des-cbc DES in CBC mode
des Alias for des-cbc
des-cfb DES in CFB mode
des-ofb DES in OFB mode
des-ecb DES in ECB mode
des-ede-cbc Two key triple DES EDE in CBC mode
des-ede Two key triple DES EDE in ECB mode
des-ede-cfb Two key triple DES EDE in CFB mode
des-ede-ofb Two key triple DES EDE in OFB mode
des-ede3-cbc Three key triple DES EDE in CBC mode
des-ede3 Three key triple DES EDE in ECB mode
des3 Alias for des-ede3-cbc
des-ede3-cfb Three key triple DES EDE CFB mode
des-ede3-ofb Three key triple DES EDE in OFB mode
desx DESX algorithm.
gost89 GOST 28147-89 in CFB mode (provided by ccgost engine)
gost89-cnt GOST 28147-89 in CNT mode (provided by ccgost engine)
idea-cbc IDEA algorithm in CBC mode
idea same as idea-cbc
idea-cfb IDEA in CFB mode
idea-ecb IDEA in ECB mode
idea-ofb IDEA in OFB mode
rc2-cbc 128 bit RC2 in CBC mode
rc2 Alias for rc2-cbc
rc2-cfb 128 bit RC2 in CFB mode
rc2-ecb 128 bit RC2 in ECB mode
rc2-ofb 128 bit RC2 in OFB mode
rc2-64-cbc 64 bit RC2 in CBC mode
rc2-40-cbc 40 bit RC2 in CBC mode
rc4 128 bit RC4
rc4-64 64 bit RC4
rc4-40 40 bit RC4
rc5-cbc RC5 cipher in CBC mode
rc5 Alias for rc5-cbc
rc5-cfb RC5 cipher in CFB mode
rc5-ecb RC5 cipher in ECB mode
rc5-ofb RC5 cipher in OFB mode
seed-cbc SEED cipher in CBC mode
seed Alias for seed-cbc
seed-cfb SEED cipher in CFB mode
seed-ecb SEED cipher in ECB mode
seed-ofb SEED cipher in OFB mode
sm4-cbc SM4 cipher in CBC mode
sm4 Alias for sm4-cbc
sm4-cfb SM4 cipher in CFB mode
sm4-ctr SM4 cipher in CTR mode
sm4-ecb SM4 cipher in ECB mode
sm4-ofb SM4 cipher in OFB mode
aes-[128|192|256]-cbc 128/192/256 bit AES in CBC mode
aes[128|192|256] Alias for aes-[128|192|256]-cbc
aes-[128|192|256]-cfb 128/192/256 bit AES in 128 bit CFB mode
aes-[128|192|256]-cfb1 128/192/256 bit AES in 1 bit CFB mode
aes-[128|192|256]-cfb8 128/192/256 bit AES in 8 bit CFB mode
aes-[128|192|256]-ctr 128/192/256 bit AES in CTR mode
aes-[128|192|256]-ecb 128/192/256 bit AES in ECB mode
aes-[128|192|256]-ofb 128/192/256 bit AES in OFB mode
aria-[128|192|256]-cbc 128/192/256 bit ARIA in CBC mode
aria[128|192|256] Alias for aria-[128|192|256]-cbc
aria-[128|192|256]-cfb 128/192/256 bit ARIA in 128 bit CFB mode
aria-[128|192|256]-cfb1 128/192/256 bit ARIA in 1 bit CFB mode
aria-[128|192|256]-cfb8 128/192/256 bit ARIA in 8 bit CFB mode
aria-[128|192|256]-ctr 128/192/256 bit ARIA in CTR mode
aria-[128|192|256]-ecb 128/192/256 bit ARIA in ECB mode
aria-[128|192|256]-ofb 128/192/256 bit ARIA in OFB mode
camellia-[128|192|256]-cbc 128/192/256 bit Camellia in CBC mode
camellia[128|192|256] Alias for camellia-[128|192|256]-cbc
camellia-[128|192|256]-cfb 128/192/256 bit Camellia in 128 bit CFB mode
camellia-[128|192|256]-cfb1 128/192/256 bit Camellia in 1 bit CFB mode
camellia-[128|192|256]-cfb8 128/192/256 bit Camellia in 8 bit CFB mode
camellia-[128|192|256]-ctr 128/192/256 bit Camellia in CTR mode
camellia-[128|192|256]-ecb 128/192/256 bit Camellia in ECB mode
camellia-[128|192|256]-ofb 128/192/256 bit Camellia in OFB mode
=head1 EXAMPLES
Just base64 encode a binary file:
openssl base64 -in file.bin -out file.b64
Decode the same file
openssl base64 -d -in file.b64 -out file.bin
Encrypt a file using AES-128 using a prompted password
and PBKDF2 key derivation:
openssl enc -aes128 -pbkdf2 -in file.txt -out file.aes128
Decrypt a file using a supplied password:
openssl enc -aes128 -pbkdf2 -d -in file.aes128 -out file.txt \
-pass pass:<password>
Encrypt a file then base64 encode it (so it can be sent via mail for example)
using AES-256 in CTR mode and PBKDF2 key derivation:
openssl enc -aes-256-ctr -pbkdf2 -a -in file.txt -out file.aes256
Base64 decode a file then decrypt it using a password supplied in a file:
openssl enc -aes-256-ctr -pbkdf2 -d -a -in file.aes256 -out file.txt \
-pass file:<passfile>
=head1 BUGS
The B<-A> option when used with large files doesn't work properly.
The B<openssl enc> command only supports a fixed number of algorithms with
certain parameters. So if, for example, you want to use RC2 with a
76 bit key or RC4 with an 84 bit key you can't use this program.
=head1 HISTORY
The default digest was changed from MD5 to SHA256 in OpenSSL 1.1.0.
The B<-list> option was added in OpenSSL 1.1.1e.
The B<-ciphers> and B<-engine> options were deprecated 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/doc/man1/openssl.pod b/doc/man1/openssl.pod
index 869e8e5ad8a1..201428e87004 100644
--- a/doc/man1/openssl.pod
+++ b/doc/man1/openssl.pod
@@ -1,841 +1,843 @@
=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 DLTS.
+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)>.
For information about all environment variables used by the OpenSSL libraries,
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.
=back
=back
=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-2022 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man3/ASN1_STRING_new.pod b/doc/man3/ASN1_STRING_new.pod
index ff20de73b7b9..642b6f47777b 100644
--- a/doc/man3/ASN1_STRING_new.pod
+++ b/doc/man3/ASN1_STRING_new.pod
@@ -1,52 +1,52 @@
=pod
=head1 NAME
ASN1_STRING_new, ASN1_STRING_type_new, ASN1_STRING_free -
ASN1_STRING allocation functions
=head1 SYNOPSIS
#include <openssl/asn1.h>
ASN1_STRING *ASN1_STRING_new(void);
ASN1_STRING *ASN1_STRING_type_new(int type);
void ASN1_STRING_free(ASN1_STRING *a);
=head1 DESCRIPTION
ASN1_STRING_new() returns an allocated B<ASN1_STRING> structure. Its type
is undefined.
ASN1_STRING_type_new() returns an allocated B<ASN1_STRING> structure of
type I<type>.
ASN1_STRING_free() frees up I<a>.
If I<a> is NULL nothing is done.
=head1 NOTES
Other string types call the B<ASN1_STRING> functions. For example
-ASN1_OCTET_STRING_new() calls ASN1_STRING_type(V_ASN1_OCTET_STRING).
+ASN1_OCTET_STRING_new() calls ASN1_STRING_type_new(V_ASN1_OCTET_STRING).
=head1 RETURN VALUES
ASN1_STRING_new() and ASN1_STRING_type_new() return a valid
B<ASN1_STRING> structure or NULL if an error occurred.
ASN1_STRING_free() does not return a value.
=head1 SEE ALSO
L<ERR_get_error(3)>
=head1 COPYRIGHT
-Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/CMS_EncryptedData_decrypt.pod b/doc/man3/CMS_EncryptedData_decrypt.pod
index 17850a98af3f..3aa3f474fc5a 100644
--- a/doc/man3/CMS_EncryptedData_decrypt.pod
+++ b/doc/man3/CMS_EncryptedData_decrypt.pod
@@ -1,49 +1,49 @@
=pod
=head1 NAME
CMS_EncryptedData_decrypt
- Decrypt CMS EncryptedData
=head1 SYNOPSIS
#include <openssl/cms.h>
int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
const unsigned char *key, size_t keylen,
BIO *dcont, BIO *out, unsigned int flags);
=head1 DESCRIPTION
CMS_EncryptedData_decrypt() decrypts a I<cms> EncryptedData object using the
symmetric I<key> of size I<keylen> bytes. I<out> is a BIO to write the content
to and I<flags> is an optional set of flags.
I<dcont> is used in the rare case where the encrypted content is detached. It
will normally be set to NULL.
-The following flags can be passed in the B<flags> parameter.
+The following flags can be passed in the I<flags> parameter.
-If the B<CMS_TEXT> flag is set MIME headers for type B<text/plain> are deleted
-from the content. If the content is not of type B<text/plain> then an error is
+If the B<CMS_TEXT> flag is set MIME headers for type C<text/plain> are deleted
+from the content. If the content is not of type C<text/plain> then an error is
returned.
=head1 RETURN VALUES
CMS_EncryptedData_decrypt() returns 0 if an error occurred otherwise it
returns 1.
=head1 SEE ALSO
L<ERR_get_error(3)>, L<CMS_EncryptedData_encrypt(3)>
=head1 COPYRIGHT
-Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man3/CMS_add0_cert.pod b/doc/man3/CMS_add0_cert.pod
index 734db9f7b972..8908ff2f1fc0 100644
--- a/doc/man3/CMS_add0_cert.pod
+++ b/doc/man3/CMS_add0_cert.pod
@@ -1,78 +1,80 @@
=pod
=head1 NAME
CMS_add0_cert, CMS_add1_cert, CMS_get1_certs, CMS_add0_crl, CMS_add1_crl, CMS_get1_crls
- CMS certificate and CRL utility functions
=head1 SYNOPSIS
#include <openssl/cms.h>
int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert);
int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert);
STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms);
int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl);
int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl);
STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms);
=head1 DESCRIPTION
CMS_add0_cert() and CMS_add1_cert() add certificate I<cert> to I<cms>.
+This is used by L<CMS_sign_ex(3)> and L<CMS_sign(3)> and may be used before
+calling L<CMS_verify(3)> to help chain building in certificate validation.
I<cms> must be of type signed data or (authenticated) enveloped data.
For signed data, such a certificate can be used when signing or verifying
to fill in the signer certificate or to provide an extra CA certificate
that may be needed for chain building in certificate validation.
CMS_get1_certs() returns all certificates in I<cms>.
CMS_add0_crl() and CMS_add1_crl() add CRL I<crl> to I<cms>.
I<cms> must be of type signed data or (authenticated) enveloped data.
-For signed data, such a CRL may be used in certificate validation.
+For signed data, such a CRL may be used in certificate validation
+with L<CMS_verify(3)>.
It may be given both for inclusion when signing a CMS message
and when verifying a signed CMS message.
CMS_get1_crls() returns all CRLs in I<cms>.
=head1 NOTES
The CMS_ContentInfo structure I<cms> must be of type signed data or enveloped
data or an error will be returned.
For signed data certificates and CRLs are added to the I<certificates> and
I<crls> fields of SignedData structure. For enveloped data they are added to
B<OriginatorInfo>.
As the I<0> implies CMS_add0_cert() adds I<cert> internally to I<cms> and it
must not be freed up after the call as opposed to CMS_add1_cert() where I<cert>
must be freed up.
-The same certificate or CRL must not be added to the same cms structure more
-than once.
+The same certificate must not be added to the same cms structure more than once.
=head1 RETURN VALUES
CMS_add0_cert(), CMS_add1_cert() and CMS_add0_crl() and CMS_add1_crl() return
1 for success and 0 for failure.
CMS_get1_certs() and CMS_get1_crls() return the STACK of certificates or CRLs
or NULL if there are none or an error occurs. The only error which will occur
in practice is if the I<cms> type is invalid.
=head1 SEE ALSO
L<ERR_get_error(3)>,
-L<CMS_sign(3)>,
+L<CMS_sign(3)>, L<CMS_sign_ex(3)>, L<CMS_verify(3)>,
L<CMS_encrypt(3)>
=head1 COPYRIGHT
-Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/CMS_decrypt.pod b/doc/man3/CMS_decrypt.pod
index 4f8d32fbbb24..75c33a91d176 100644
--- a/doc/man3/CMS_decrypt.pod
+++ b/doc/man3/CMS_decrypt.pod
@@ -1,97 +1,123 @@
=pod
=head1 NAME
-CMS_decrypt, CMS_decrypt_set1_pkey_and_peer, CMS_decrypt_set1_pkey - decrypt
-content from a CMS envelopedData structure
+CMS_decrypt, CMS_decrypt_set1_pkey_and_peer,
+CMS_decrypt_set1_pkey, CMS_decrypt_set1_password
+- decrypt content from a CMS envelopedData structure
=head1 SYNOPSIS
#include <openssl/cms.h>
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
BIO *dcont, BIO *out, unsigned int flags);
int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms,
EVP_PKEY *pk, X509 *cert, X509 *peer);
int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
+ int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
+ unsigned char *pass, ossl_ssize_t passlen);
=head1 DESCRIPTION
-CMS_decrypt() extracts and decrypts the content from a CMS EnvelopedData
-or AuthEnvelopedData structure. B<pkey> is the private key of the recipient,
-B<cert> is the recipient's certificate, B<out> is a BIO to write the content to
-and B<flags> is an optional set of flags.
-
-The B<dcont> parameter is used in the rare case where the encrypted content
+CMS_decrypt() extracts the decrypted content from a CMS EnvelopedData
+or AuthEnvelopedData structure.
+It uses CMS_decrypt_set1_pkey() to decrypt the content
+with the recipient private key I<pkey> if I<pkey> is not NULL.
+In this case, it is recommended to provide the associated certificate
+in I<cert> - see the NOTES below.
+I<out> is a BIO to write the content to and
+I<flags> is an optional set of flags.
+If I<pkey> is NULL the function assumes that decryption was already done
+(e.g., using CMS_decrypt_set1_pkey() or CMS_decrypt_set1_password()) and just
+provides the content unless I<cert>, I<dcont>, and I<out> are NULL as well.
+The I<dcont> parameter is used in the rare case where the encrypted content
is detached. It will normally be set to NULL.
-CMS_decrypt_set1_pkey_and_peer() associates the private key B<pkey>, the
-corresponding certificate B<cert> and the originator certificate B<peer> with
-the CMS_ContentInfo structure B<cms>.
+CMS_decrypt_set1_pkey_and_peer() decrypts the CMS_ContentInfo structure I<cms>
+using the private key I<pkey>, the corresponding certificate I<cert>, which is
+recommended to be supplied but may be NULL,
+and the (optional) originator certificate I<peer>.
+On success, it also records in I<cms> the decryption key I<pkey>, and this
+should be followed by C<CMS_decrypt(cms, NULL, NULL, dcont, out, flags)>.
+This call deallocates any decryption key stored in I<cms>.
+
+CMS_decrypt_set1_pkey() is the same as
+CMS_decrypt_set1_pkey_and_peer() with I<peer> being NULL.
-CMS_decrypt_set1_pkey() associates the private key B<pkey>, corresponding
-certificate B<cert> with the CMS_ContentInfo structure B<cms>.
+CMS_decrypt_set1_password() decrypts the CMS_ContentInfo structure I<cms>
+using the secret I<pass> of length I<passlen>.
+On success, it also records in I<cms> the decryption key used, and this
+should be followed by C<CMS_decrypt(cms, NULL, NULL, dcont, out, flags)>.
+This call deallocates any decryption key stored in I<cms>.
=head1 NOTES
Although the recipients certificate is not needed to decrypt the data it is
needed to locate the appropriate (of possible several) recipients in the CMS
structure.
-If B<cert> is set to NULL all possible recipients are tried. This case however
+If I<cert> is set to NULL all possible recipients are tried. This case however
is problematic. To thwart the MMA attack (Bleichenbacher's attack on
PKCS #1 v1.5 RSA padding) all recipients are tried whether they succeed or
not. If no recipient succeeds then a random symmetric key is used to decrypt
the content: this will typically output garbage and may (but is not guaranteed
to) ultimately return a padding error only. If CMS_decrypt() just returned an
error when all recipient encrypted keys failed to decrypt an attacker could
use this in a timing attack. If the special flag B<CMS_DEBUG_DECRYPT> is set
then the above behaviour is modified and an error B<is> returned if no
recipient encrypted key can be decrypted B<without> generating a random
content encryption key. Applications should use this flag with
B<extreme caution> especially in automated gateways as it can leave them
open to attack.
It is possible to determine the correct recipient key by other means (for
example looking them up in a database) and setting them in the CMS structure
-in advance using the CMS utility functions such as CMS_set1_pkey(). In this
-case both B<cert> and B<pkey> should be set to NULL.
+in advance using the CMS utility functions such as CMS_set1_pkey(),
+or use CMS_decrypt_set1_password() if the recipient has a symmetric key.
+In these cases both I<cert> and I<pkey> should be set to NULL.
To process KEKRecipientInfo types CMS_set1_key() or CMS_RecipientInfo_set0_key()
and CMS_RecipientInfo_decrypt() should be called before CMS_decrypt() and
-B<cert> and B<pkey> set to NULL.
+I<cert> and I<pkey> set to NULL.
-The following flags can be passed in the B<flags> parameter.
+The following flags can be passed in the I<flags> parameter.
-If the B<CMS_TEXT> flag is set MIME headers for type B<text/plain> are deleted
-from the content. If the content is not of type B<text/plain> then an error is
+If the B<CMS_TEXT> flag is set MIME headers for type C<text/plain> are deleted
+from the content. If the content is not of type C<text/plain> then an error is
returned.
=head1 RETURN VALUES
-CMS_decrypt() returns either 1 for success or 0 for failure.
-The error can be obtained from ERR_get_error(3)
+CMS_decrypt(), CMS_decrypt_set1_pkey_and_peer(),
+CMS_decrypt_set1_pkey(), and CMS_decrypt_set1_password()
+return either 1 for success or 0 for failure.
+The error can be obtained from ERR_get_error(3).
=head1 BUGS
+The B<set1_> part of these function names is misleading
+and should better read: B<with_>.
+
The lack of single pass processing and the need to hold all data in memory as
mentioned in CMS_verify() also applies to CMS_decrypt().
=head1 SEE ALSO
L<ERR_get_error(3)>, L<CMS_encrypt(3)>
=head1 HISTORY
-B<CMS_decrypt_set1_pkey_and_peer> was added in OpenSSL 3.0.
+CMS_decrypt_set1_pkey_and_peer() and CMS_decrypt_set1_password()
+were added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EC_GROUP_copy.pod b/doc/man3/EC_GROUP_copy.pod
index 651f059d4fd5..e525fad0bf6b 100644
--- a/doc/man3/EC_GROUP_copy.pod
+++ b/doc/man3/EC_GROUP_copy.pod
@@ -1,262 +1,262 @@
=pod
=head1 NAME
EC_GROUP_get0_order, EC_GROUP_order_bits, EC_GROUP_get0_cofactor,
EC_GROUP_copy, EC_GROUP_dup, EC_GROUP_method_of, EC_GROUP_set_generator,
EC_GROUP_get0_generator, EC_GROUP_get_order, EC_GROUP_get_cofactor,
EC_GROUP_set_curve_name, EC_GROUP_get_curve_name, EC_GROUP_set_asn1_flag,
EC_GROUP_get_asn1_flag, EC_GROUP_set_point_conversion_form,
EC_GROUP_get_point_conversion_form, EC_GROUP_get0_seed,
EC_GROUP_get_seed_len, EC_GROUP_set_seed, EC_GROUP_get_degree,
EC_GROUP_check, EC_GROUP_check_named_curve,
EC_GROUP_check_discriminant, EC_GROUP_cmp,
EC_GROUP_get_basis_type, EC_GROUP_get_trinomial_basis,
EC_GROUP_get_pentanomial_basis, EC_GROUP_get0_field,
EC_GROUP_get_field_type
- Functions for manipulating EC_GROUP objects
=head1 SYNOPSIS
#include <openssl/ec.h>
int EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src);
EC_GROUP *EC_GROUP_dup(const EC_GROUP *src);
int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
const BIGNUM *order, const BIGNUM *cofactor);
const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group);
int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx);
const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group);
int EC_GROUP_order_bits(const EC_GROUP *group);
int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx);
const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group);
const BIGNUM *EC_GROUP_get0_field(const EC_GROUP *group);
void EC_GROUP_set_curve_name(EC_GROUP *group, int nid);
int EC_GROUP_get_curve_name(const EC_GROUP *group);
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag);
int EC_GROUP_get_asn1_flag(const EC_GROUP *group);
void EC_GROUP_set_point_conversion_form(EC_GROUP *group, point_conversion_form_t form);
point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group);
unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group);
size_t EC_GROUP_get_seed_len(const EC_GROUP *group);
size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *, size_t len);
int EC_GROUP_get_degree(const EC_GROUP *group);
int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx);
int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only,
BN_CTX *ctx);
int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx);
int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx);
int EC_GROUP_get_basis_type(const EC_GROUP *group);
int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k);
int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
unsigned int *k2, unsigned int *k3);
int EC_GROUP_get_field_type(const EC_GROUP *group);
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 EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group);
=head1 DESCRIPTION
EC_GROUP_copy() copies the curve B<src> into B<dst>. Both B<src> and B<dst> must use the same EC_METHOD.
EC_GROUP_dup() creates a new EC_GROUP object and copies the content from B<src> to the newly created
EC_GROUP object.
EC_GROUP_method_of() obtains the EC_METHOD of B<group>.
This function was deprecated in OpenSSL 3.0, since EC_METHOD is no longer a public concept.
EC_GROUP_set_generator() sets curve parameters that must be agreed by all participants using the curve. These
parameters include the B<generator>, the B<order> and the B<cofactor>. The B<generator> is a well defined point on the
curve chosen for cryptographic operations. Integers used for point multiplications will be between 0 and
n-1 where n is the B<order>. The B<order> multiplied by the B<cofactor> gives the number of points on the curve.
EC_GROUP_get0_generator() returns the generator for the identified B<group>.
EC_GROUP_get_order() retrieves the order of B<group> and copies its value into
B<order>. It fails in case B<group> is not fully initialized (i.e., its order
is not set or set to zero).
EC_GROUP_get_cofactor() retrieves the cofactor of B<group> and copies its value
into B<cofactor>. It fails in case B<group> is not fully initialized or if the
cofactor is not set (or set to zero).
The functions EC_GROUP_set_curve_name() and EC_GROUP_get_curve_name(), set and get the NID for the curve respectively
(see L<EC_GROUP_new(3)>). If a curve does not have a NID associated with it, then EC_GROUP_get_curve_name
will return NID_undef.
The asn1_flag value is used to determine whether the curve encoding uses
explicit parameters or a named curve using an ASN1 OID: many applications only
support the latter form. If asn1_flag is B<OPENSSL_EC_NAMED_CURVE> then the
named curve form is used and the parameters must have a corresponding
named curve NID set. If asn1_flags is B<OPENSSL_EC_EXPLICIT_CURVE> the
parameters are explicitly encoded. The functions EC_GROUP_get_asn1_flag() and
EC_GROUP_set_asn1_flag() get and set the status of the asn1_flag for the curve.
Note: B<OPENSSL_EC_EXPLICIT_CURVE> was added in OpenSSL 1.1.0, for
previous versions of OpenSSL the value 0 must be used instead. Before OpenSSL
1.1.0 the default form was to use explicit parameters (meaning that
applications would have to explicitly set the named curve form) in OpenSSL
1.1.0 and later the named curve form is the default.
The point_conversion_form for a curve controls how EC_POINT data is encoded as ASN1 as defined in X9.62 (ECDSA).
point_conversion_form_t is an enum defined as follows:
typedef enum {
/** the point is encoded as z||x, where the octet z specifies
* which solution of the quadratic equation y is */
POINT_CONVERSION_COMPRESSED = 2,
/** the point is encoded as z||x||y, where z is the octet 0x04 */
POINT_CONVERSION_UNCOMPRESSED = 4,
/** the point is encoded as z||x||y, where the octet z specifies
* which solution of the quadratic equation y is */
POINT_CONVERSION_HYBRID = 6
} point_conversion_form_t;
For POINT_CONVERSION_UNCOMPRESSED the point is encoded as an octet signifying the UNCOMPRESSED form has been used followed by
the octets for x, followed by the octets for y.
-For any given x co-ordinate for a point on a curve it is possible to derive two possible y values. For
+For any given x coordinate for a point on a curve it is possible to derive two possible y values. For
POINT_CONVERSION_COMPRESSED the point is encoded as an octet signifying that the COMPRESSED form has been used AND which of
the two possible solutions for y has been used, followed by the octets for x.
For POINT_CONVERSION_HYBRID the point is encoded as an octet signifying the HYBRID form has been used AND which of the two
possible solutions for y has been used, followed by the octets for x, followed by the octets for y.
The functions EC_GROUP_set_point_conversion_form() and EC_GROUP_get_point_conversion_form(), set and get the point_conversion_form
for the curve respectively.
ANSI X9.62 (ECDSA standard) defines a method of generating the curve parameter b from a random number. This provides advantages
in that a parameter obtained in this way is highly unlikely to be susceptible to special purpose attacks, or have any trapdoors in it.
If the seed is present for a curve then the b parameter was generated in a verifiable fashion using that seed. The OpenSSL EC library
does not use this seed value but does enable you to inspect it using EC_GROUP_get0_seed(). This returns a pointer to a memory block
containing the seed that was used. The length of the memory block can be obtained using EC_GROUP_get_seed_len(). A number of the
built-in curves within the library provide seed values that can be obtained. It is also possible to set a custom seed using
EC_GROUP_set_seed() and passing a pointer to a memory block, along with the length of the seed. Again, the EC library will not use
this seed value, although it will be preserved in any ASN1 based communications.
EC_GROUP_get_degree() gets the degree of the field.
For Fp fields this will be the number of bits in p.
For F2^m fields this will be the value m.
EC_GROUP_get_field_type() identifies what type of field the EC_GROUP structure supports,
which will be either F2^m or Fp.
The function EC_GROUP_check_discriminant() calculates the discriminant for the curve and verifies that it is valid.
For a curve defined over Fp the discriminant is given by the formula 4*a^3 + 27*b^2 whilst for F2^m curves the discriminant is
simply b. In either case for the curve to be valid the discriminant must be non zero.
The function EC_GROUP_check() behaves in the following way:
For the OpenSSL default provider it performs a number of checks on a curve to verify that it is valid. Checks performed include
verifying that the discriminant is non zero; that a generator has been defined; that the generator is on the curve and has
the correct order. For the OpenSSL FIPS provider it uses EC_GROUP_check_named_curve() to conform to SP800-56Ar3.
The function EC_GROUP_check_named_curve() determines if the group's domain parameters match one of the built-in curves supported by the library.
The curve name is returned as a B<NID> if it matches. If the group's domain parameters have been modified then no match will be found.
If the curve name of the given group is B<NID_undef> (e.g. it has been created by using explicit parameters with no curve name),
then this method can be used to lookup the name of the curve that matches the group domain parameters. The built-in curves contain
aliases, so that multiple NID's can map to the same domain parameters. For such curves it is unspecified which of the aliases will be
returned if the curve name of the given group is NID_undef.
If B<nist_only> is 1 it will only look for NIST approved curves, otherwise it searches all built-in curves.
This function may be passed a BN_CTX object in the B<ctx> parameter.
The B<ctx> parameter may be NULL.
EC_GROUP_cmp() compares B<a> and B<b> to determine whether they represent the same curve or not.
The functions EC_GROUP_get_basis_type(), EC_GROUP_get_trinomial_basis() and EC_GROUP_get_pentanomial_basis() should only be called for curves
defined over an F2^m field. Addition and multiplication operations within an F2^m field are performed using an irreducible polynomial
function f(x). This function is either a trinomial of the form:
f(x) = x^m + x^k + 1 with m > k >= 1
or a pentanomial of the form:
f(x) = x^m + x^k3 + x^k2 + x^k1 + 1 with m > k3 > k2 > k1 >= 1
The function EC_GROUP_get_basis_type() returns a NID identifying whether a trinomial or pentanomial is in use for the field. The
function EC_GROUP_get_trinomial_basis() must only be called where f(x) is of the trinomial form, and returns the value of B<k>. Similarly
the function EC_GROUP_get_pentanomial_basis() must only be called where f(x) is of the pentanomial form, and returns the values of B<k1>,
B<k2> and B<k3> respectively.
=head1 RETURN VALUES
The following functions return 1 on success or 0 on error: EC_GROUP_copy(), EC_GROUP_set_generator(), EC_GROUP_check(),
EC_GROUP_check_discriminant(), EC_GROUP_get_trinomial_basis() and EC_GROUP_get_pentanomial_basis().
EC_GROUP_dup() returns a pointer to the duplicated curve, or NULL on error.
EC_GROUP_method_of() returns the EC_METHOD implementation in use for the given curve or NULL on error.
EC_GROUP_get0_generator() returns the generator for the given curve or NULL on error.
EC_GROUP_get_order() returns 0 if the order is not set (or set to zero) for
B<group> or if copying into B<order> fails, 1 otherwise.
EC_GROUP_get_cofactor() returns 0 if the cofactor is not set (or is set to zero) for B<group> or if copying into B<cofactor> fails, 1 otherwise.
EC_GROUP_get_curve_name() returns the curve name (NID) for B<group> or will return NID_undef if no curve name is associated.
EC_GROUP_get_asn1_flag() returns the ASN1 flag for the specified B<group> .
EC_GROUP_get_point_conversion_form() returns the point_conversion_form for B<group>.
EC_GROUP_get_degree() returns the degree for B<group> or 0 if the operation is not supported by the underlying group implementation.
EC_GROUP_get_field_type() returns either B<NID_X9_62_prime_field> for prime curves
or B<NID_X9_62_characteristic_two_field> for binary curves;
these values are defined in the F<< <openssl/obj_mac.h> >> header file.
EC_GROUP_check_named_curve() returns the nid of the matching named curve, otherwise it returns 0 for no match, or -1 on error.
EC_GROUP_get0_order() returns an internal pointer to the group order.
EC_GROUP_order_bits() returns the number of bits in the group order.
EC_GROUP_get0_cofactor() returns an internal pointer to the group cofactor.
EC_GROUP_get0_field() returns an internal pointer to the group field. For curves over GF(p), this is the modulus; for curves
over GF(2^m), this is the irreducible polynomial defining the field.
EC_GROUP_get0_seed() returns a pointer to the seed that was used to generate the parameter b, or NULL if the seed is not
specified. EC_GROUP_get_seed_len() returns the length of the seed or 0 if the seed is not specified.
EC_GROUP_set_seed() returns the length of the seed that has been set. If the supplied seed is NULL, or the supplied seed length is
0, the return value will be 1. On error 0 is returned.
EC_GROUP_cmp() returns 0 if the curves are equal, 1 if they are not equal, or -1 on error.
EC_GROUP_get_basis_type() returns the values NID_X9_62_tpBasis or NID_X9_62_ppBasis (as defined in F<< <openssl/obj_mac.h> >>) for a
trinomial or pentanomial respectively. Alternatively in the event of an error a 0 is returned.
=head1 SEE ALSO
L<crypto(7)>, L<EC_GROUP_new(3)>,
L<EC_POINT_new(3)>, L<EC_POINT_add(3)>, L<EC_KEY_new(3)>,
L<EC_GFp_simple_method(3)>, L<d2i_ECPKParameters(3)>
=head1 HISTORY
EC_GROUP_method_of() was deprecated in OpenSSL 3.0.
EC_GROUP_get0_field(), EC_GROUP_check_named_curve() and EC_GROUP_get_field_type() were added in OpenSSL 3.0.
EC_GROUP_get0_order(), EC_GROUP_order_bits() and EC_GROUP_get0_cofactor() were added in OpenSSL 1.1.0.
=head1 COPYRIGHT
Copyright 2013-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/doc/man3/EC_KEY_new.pod b/doc/man3/EC_KEY_new.pod
index e611b4d691f1..d93586b1d01e 100644
--- a/doc/man3/EC_KEY_new.pod
+++ b/doc/man3/EC_KEY_new.pod
@@ -1,245 +1,245 @@
=pod
=head1 NAME
EVP_EC_gen,
EC_KEY_get_method, EC_KEY_set_method, EC_KEY_new_ex,
EC_KEY_new, EC_KEY_get_flags, EC_KEY_set_flags, EC_KEY_clear_flags,
EC_KEY_new_by_curve_name_ex, EC_KEY_new_by_curve_name, EC_KEY_free,
EC_KEY_copy, EC_KEY_dup, EC_KEY_up_ref, EC_KEY_get0_engine,
EC_KEY_get0_group, EC_KEY_set_group, EC_KEY_get0_private_key,
EC_KEY_set_private_key, EC_KEY_get0_public_key, EC_KEY_set_public_key,
EC_KEY_get_conv_form,
EC_KEY_set_conv_form, EC_KEY_set_asn1_flag,
EC_KEY_decoded_from_explicit_params, EC_KEY_precompute_mult,
EC_KEY_generate_key, EC_KEY_check_key, EC_KEY_set_public_key_affine_coordinates,
EC_KEY_oct2key, EC_KEY_key2buf, EC_KEY_oct2priv, EC_KEY_priv2oct,
EC_KEY_priv2buf - Functions for creating, destroying and manipulating
EC_KEY objects
=head1 SYNOPSIS
#include <openssl/ec.h>
EVP_PKEY *EVP_EC_gen(const char *curve);
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)>:
EC_KEY *EC_KEY_new_ex(OSSL_LIB_CTX *ctx, const char *propq);
EC_KEY *EC_KEY_new(void);
int EC_KEY_get_flags(const EC_KEY *key);
void EC_KEY_set_flags(EC_KEY *key, int flags);
void EC_KEY_clear_flags(EC_KEY *key, int flags);
EC_KEY *EC_KEY_new_by_curve_name_ex(OSSL_LIB_CTX *ctx, const char *propq,
int nid);
EC_KEY *EC_KEY_new_by_curve_name(int nid);
void EC_KEY_free(EC_KEY *key);
EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src);
EC_KEY *EC_KEY_dup(const EC_KEY *src);
int EC_KEY_up_ref(EC_KEY *key);
ENGINE *EC_KEY_get0_engine(const EC_KEY *eckey);
const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key);
int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group);
const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key);
int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key);
const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key);
int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub);
point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key);
void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform);
void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag);
int EC_KEY_decoded_from_explicit_params(const EC_KEY *key);
int EC_KEY_generate_key(EC_KEY *key);
int EC_KEY_check_key(const EC_KEY *key);
int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y);
const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key);
int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth);
int EC_KEY_oct2key(EC_KEY *eckey, const unsigned char *buf, size_t len, BN_CTX *ctx);
size_t EC_KEY_key2buf(const EC_KEY *eckey, point_conversion_form_t form,
unsigned char **pbuf, BN_CTX *ctx);
int EC_KEY_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len);
size_t EC_KEY_priv2oct(const EC_KEY *eckey, unsigned char *buf, size_t len);
size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf);
int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx);
=head1 DESCRIPTION
EVP_EC_gen() generates a new EC key pair on the given I<curve>.
All of the functions described below are deprecated.
Applications should instead use EVP_EC_gen(), L<EVP_PKEY_Q_keygen(3)>, or
L<EVP_PKEY_keygen_init(3)> and L<EVP_PKEY_keygen(3)>.
An EC_KEY represents a public key and, optionally, the associated private
key.
A new EC_KEY with no associated curve can be constructed by calling
EC_KEY_new_ex() and specifying the associated library context in I<ctx>
(see L<OSSL_LIB_CTX(3)>) and property query string I<propq>.
The I<ctx> parameter may be NULL in which case the default library context is
used.
The reference count for the newly created EC_KEY is initially
set to 1.
A curve can be associated with the EC_KEY by calling
EC_KEY_set_group().
EC_KEY_new() is the same as EC_KEY_new_ex() except that the default library
context is always used.
Alternatively a new EC_KEY can be constructed by calling
EC_KEY_new_by_curve_name_ex() and supplying the nid of the associated
curve, the library context to be used I<ctx> (see L<OSSL_LIB_CTX(3)>) and any
property query string I<propq>.
The I<ctx> parameter may be NULL in which case the default library context is
used. The I<propq> value may also be NULL.
See L<EC_GROUP_new(3)> for a description of curve names.
This function simply wraps calls to EC_KEY_new_ex() and
EC_GROUP_new_by_curve_name_ex().
EC_KEY_new_by_curve_name() is the same as EC_KEY_new_by_curve_name_ex()
except that the default library context is always used and a NULL property query
string.
Calling EC_KEY_free() decrements the reference count for the EC_KEY object,
and if it has dropped to zero then frees the memory associated with it. If
I<key> is NULL nothing is done.
EC_KEY_copy() copies the contents of the EC_KEY in I<src> into I<dest>.
EC_KEY_dup() creates a new EC_KEY object and copies I<ec_key> into it.
EC_KEY_up_ref() increments the reference count associated with the EC_KEY
object.
EC_KEY_get0_engine() returns a handle to the ENGINE that has been set for
this EC_KEY object.
EC_KEY_generate_key() generates a new public and private key for the supplied
I<eckey> object. I<eckey> must have an EC_GROUP object associated with it
before calling this function. The private key is a random integer (0 < priv_key
< order, where I<order> is the order of the EC_GROUP object). The public key is
an EC_POINT on the curve calculated by multiplying the generator for the
curve by the private key.
EC_KEY_check_key() performs various sanity checks on the EC_KEY object to
confirm that it is valid.
EC_KEY_set_public_key_affine_coordinates() sets the public key for I<key> based
-on its affine co-ordinates; i.e., it constructs an EC_POINT object based on
+on its affine coordinates; i.e., it constructs an EC_POINT object based on
the supplied I<x> and I<y> values and sets the public key to be this
EC_POINT. It also performs certain sanity checks on the key to confirm
that it is valid.
The functions EC_KEY_get0_group(), EC_KEY_set_group(),
EC_KEY_get0_private_key(), EC_KEY_set_private_key(), EC_KEY_get0_public_key(),
and EC_KEY_set_public_key() get and set the EC_GROUP object, the private key,
and the EC_POINT public key for the B<key> respectively. The function
EC_KEY_set_private_key() accepts NULL as the priv_key argument to securely clear
the private key component from the EC_KEY.
The functions EC_KEY_get_conv_form() and EC_KEY_set_conv_form() get and set the
point_conversion_form for the I<key>. For a description of
point_conversion_forms please see L<EC_POINT_new(3)>.
EC_KEY_set_flags() sets the flags in the I<flags> parameter on the EC_KEY
object. Any flags that are already set are left set. The flags currently
defined are EC_FLAG_NON_FIPS_ALLOW and EC_FLAG_FIPS_CHECKED. In
addition there is the flag EC_FLAG_COFACTOR_ECDH which is specific to ECDH.
EC_KEY_get_flags() returns the current flags that are set for this EC_KEY.
EC_KEY_clear_flags() clears the flags indicated by the I<flags> parameter; all
other flags are left in their existing state.
EC_KEY_set_asn1_flag() sets the asn1_flag on the underlying EC_GROUP object
(if set). Refer to L<EC_GROUP_copy(3)> for further information on the
asn1_flag.
EC_KEY_decoded_from_explicit_params() returns 1 if the group of the I<key> was
decoded from data with explicitly encoded group parameters, -1 if the I<key>
is NULL or the group parameters are missing, and 0 otherwise.
EC_KEY_precompute_mult() stores multiples of the underlying EC_GROUP generator
for faster point multiplication. See also L<EC_POINT_add(3)>.
Modern versions should instead switch to named curves which OpenSSL has
hardcoded lookup tables for.
EC_KEY_oct2key() and EC_KEY_key2buf() are identical to the functions
EC_POINT_oct2point() and EC_POINT_point2buf() except they use the public key
EC_POINT in I<eckey>.
EC_KEY_oct2priv() and EC_KEY_priv2oct() convert between the private key
component of I<eckey> and octet form. The octet form consists of the content
octets of the I<privateKey> OCTET STRING in an I<ECPrivateKey> ASN.1 structure.
The function EC_KEY_priv2oct() must be supplied with a buffer long enough to
store the octet form. The return value provides the number of octets stored.
Calling the function with a NULL buffer will not perform the conversion but
will just return the required buffer length.
The function EC_KEY_priv2buf() allocates a buffer of suitable length and writes
an EC_KEY to it in octet format. The allocated buffer is written to I<*pbuf>
and its length is returned. The caller must free up the allocated buffer with a
call to OPENSSL_free(). Since the allocated buffer value is written to I<*pbuf>
the I<pbuf> parameter B<MUST NOT> be B<NULL>.
EC_KEY_priv2buf() converts an EC_KEY private key into an allocated buffer.
=head1 RETURN VALUES
EC_KEY_new_ex(), EC_KEY_new(), EC_KEY_new_by_curve_name_ex(),
EC_KEY_new_by_curve_name() and EC_KEY_dup() return a pointer to the newly
created EC_KEY object, or NULL on error.
EC_KEY_get_flags() returns the flags associated with the EC_KEY object as an
integer.
EC_KEY_copy() returns a pointer to the destination key, or NULL on error.
EC_KEY_get0_engine() returns a pointer to an ENGINE, or NULL if it wasn't set.
EC_KEY_up_ref(), EC_KEY_set_group(), EC_KEY_set_public_key(),
EC_KEY_precompute_mult(), EC_KEY_generate_key(), EC_KEY_check_key(),
EC_KEY_set_public_key_affine_coordinates(), EC_KEY_oct2key() and
EC_KEY_oct2priv() return 1 on success or 0 on error.
EC_KEY_set_private_key() returns 1 on success or 0 on error except when the
priv_key argument is NULL, in that case it returns 0, for legacy compatibility,
and should not be treated as an error.
EC_KEY_get0_group() returns the EC_GROUP associated with the EC_KEY.
EC_KEY_get0_private_key() returns the private key associated with the EC_KEY.
EC_KEY_get_conv_form() return the point_conversion_form for the EC_KEY.
EC_KEY_key2buf(), EC_KEY_priv2oct() and EC_KEY_priv2buf() return the length
of the buffer or 0 on error.
=head1 SEE ALSO
L<EVP_PKEY_Q_keygen(3)>
L<crypto(7)>, L<EC_GROUP_new(3)>,
L<EC_GROUP_copy(3)>, L<EC_POINT_new(3)>,
L<EC_POINT_add(3)>,
L<EC_GFp_simple_method(3)>,
L<d2i_ECPKParameters(3)>,
L<OSSL_LIB_CTX(3)>
=head1 HISTORY
EVP_EC_gen() was added in OpenSSL 3.0.
All other functions described here were deprecated in OpenSSL 3.0.
For replacement see L<EVP_PKEY-EC(7)>.
=head1 COPYRIGHT
-Copyright 2013-2022 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-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/doc/man3/EC_POINT_add.pod b/doc/man3/EC_POINT_add.pod
index 97bd34c3932e..591308be3fc2 100644
--- a/doc/man3/EC_POINT_add.pod
+++ b/doc/man3/EC_POINT_add.pod
@@ -1,100 +1,100 @@
=pod
=head1 NAME
EC_POINT_add, EC_POINT_dbl, EC_POINT_invert, EC_POINT_is_at_infinity, EC_POINT_is_on_curve, EC_POINT_cmp, EC_POINT_make_affine, EC_POINTs_make_affine, EC_POINTs_mul, EC_POINT_mul, EC_GROUP_precompute_mult, EC_GROUP_have_precompute_mult - Functions for performing mathematical operations and tests on EC_POINT objects
=head1 SYNOPSIS
#include <openssl/ec.h>
int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx);
int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx);
int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx);
int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *p);
int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx);
int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx);
int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n,
const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx);
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 EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx);
int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
EC_POINT *points[], BN_CTX *ctx);
int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, size_t num,
const EC_POINT *p[], const BIGNUM *m[], BN_CTX *ctx);
int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
int EC_GROUP_have_precompute_mult(const EC_GROUP *group);
=head1 DESCRIPTION
EC_POINT_add adds the two points B<a> and B<b> and places the result in B<r>. Similarly EC_POINT_dbl doubles the point B<a> and places the
result in B<r>. In both cases it is valid for B<r> to be one of B<a> or B<b>.
EC_POINT_invert calculates the inverse of the supplied point B<a>. The result is placed back in B<a>.
The function EC_POINT_is_at_infinity tests whether the supplied point is at infinity or not.
EC_POINT_is_on_curve tests whether the supplied point is on the curve or not.
EC_POINT_cmp compares the two supplied points and tests whether or not they are equal.
The functions EC_POINT_make_affine and EC_POINTs_make_affine force the internal representation of the EC_POINT(s) into the affine
-co-ordinate system. In the case of EC_POINTs_make_affine the value B<num> provides the number of points in the array B<points> to be
+coordinate system. In the case of EC_POINTs_make_affine the value B<num> provides the number of points in the array B<points> to be
forced. These functions were deprecated in OpenSSL 3.0 and should no longer be used.
Modern versions automatically perform this conversion when needed.
EC_POINT_mul calculates the value generator * B<n> + B<q> * B<m> and stores the result in B<r>.
The value B<n> may be NULL in which case the result is just B<q> * B<m> (variable point multiplication). Alternatively, both B<q> and B<m> may be NULL, and B<n> non-NULL, in which case the result is just generator * B<n> (fixed point multiplication).
When performing a single fixed or variable point multiplication, the underlying implementation uses a constant time algorithm, when the input scalar (either B<n> or B<m>) is in the range [0, ec_group_order).
Although deprecated in OpenSSL 3.0 and should no longer be used,
EC_POINTs_mul calculates the value generator * B<n> + B<q[0]> * B<m[0]> + ... + B<q[num-1]> * B<m[num-1]>. As for EC_POINT_mul the value B<n> may be NULL or B<num> may be zero.
When performing a fixed point multiplication (B<n> is non-NULL and B<num> is 0) or a variable point multiplication (B<n> is NULL and B<num> is 1), the underlying implementation uses a constant time algorithm, when the input scalar (either B<n> or B<m[0]>) is in the range [0, ec_group_order).
Modern versions should instead use EC_POINT_mul(), combined (if needed) with EC_POINT_add() in such rare circumstances.
The function EC_GROUP_precompute_mult stores multiples of the generator for faster point multiplication, whilst
EC_GROUP_have_precompute_mult tests whether precomputation has already been done. See L<EC_GROUP_copy(3)> for information
about the generator. Precomputation functionality was deprecated in OpenSSL 3.0.
Users of EC_GROUP_precompute_mult() and EC_GROUP_have_precompute_mult() should
switch to named curves which OpenSSL has hardcoded lookup tables for.
=head1 RETURN VALUES
The following functions return 1 on success or 0 on error: EC_POINT_add, EC_POINT_dbl, EC_POINT_invert, EC_POINT_make_affine,
EC_POINTs_make_affine, EC_POINTs_make_affine, EC_POINT_mul, EC_POINTs_mul and EC_GROUP_precompute_mult.
EC_POINT_is_at_infinity returns 1 if the point is at infinity, or 0 otherwise.
EC_POINT_is_on_curve returns 1 if the point is on the curve, 0 if not, or -1 on error.
EC_POINT_cmp returns 1 if the points are not equal, 0 if they are, or -1 on error.
EC_GROUP_have_precompute_mult return 1 if a precomputation has been done, or 0 if not.
=head1 SEE ALSO
L<crypto(7)>, L<EC_GROUP_new(3)>, L<EC_GROUP_copy(3)>,
L<EC_POINT_new(3)>, L<EC_KEY_new(3)>,
L<EC_GFp_simple_method(3)>, L<d2i_ECPKParameters(3)>
=head1 HISTORY
EC_POINT_make_affine(), EC_POINTs_make_affine(), EC_POINTs_mul(),
EC_GROUP_precompute_mult(), and EC_GROUP_have_precompute_mult()
were deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-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/doc/man3/EC_POINT_new.pod b/doc/man3/EC_POINT_new.pod
index f92cc2c8e229..3bbf8bb089ac 100644
--- a/doc/man3/EC_POINT_new.pod
+++ b/doc/man3/EC_POINT_new.pod
@@ -1,279 +1,279 @@
=pod
=head1 NAME
EC_POINT_set_Jprojective_coordinates_GFp,
EC_POINT_point2buf,
EC_POINT_new,
EC_POINT_free,
EC_POINT_clear_free,
EC_POINT_copy,
EC_POINT_dup,
EC_POINT_method_of,
EC_POINT_set_to_infinity,
EC_POINT_get_Jprojective_coordinates_GFp,
EC_POINT_set_affine_coordinates,
EC_POINT_get_affine_coordinates,
EC_POINT_set_compressed_coordinates,
EC_POINT_set_affine_coordinates_GFp,
EC_POINT_get_affine_coordinates_GFp,
EC_POINT_set_compressed_coordinates_GFp,
EC_POINT_set_affine_coordinates_GF2m,
EC_POINT_get_affine_coordinates_GF2m,
EC_POINT_set_compressed_coordinates_GF2m,
EC_POINT_point2oct,
EC_POINT_oct2point,
EC_POINT_point2bn,
EC_POINT_bn2point,
EC_POINT_point2hex,
EC_POINT_hex2point
- Functions for creating, destroying and manipulating EC_POINT objects
=head1 SYNOPSIS
#include <openssl/ec.h>
EC_POINT *EC_POINT_new(const EC_GROUP *group);
void EC_POINT_free(EC_POINT *point);
void EC_POINT_clear_free(EC_POINT *point);
int EC_POINT_copy(EC_POINT *dst, const EC_POINT *src);
EC_POINT *EC_POINT_dup(const EC_POINT *src, const EC_GROUP *group);
int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point);
int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *p,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *ctx);
int EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p,
BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *p,
const BIGNUM *x, int y_bit,
BN_CTX *ctx);
size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p,
point_conversion_form_t form,
unsigned char *buf, size_t len, BN_CTX *ctx);
size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point,
point_conversion_form_t form,
unsigned char **pbuf, BN_CTX *ctx);
int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *p,
const unsigned char *buf, size_t len, BN_CTX *ctx);
char *EC_POINT_point2hex(const EC_GROUP *group, const EC_POINT *p,
point_conversion_form_t form, BN_CTX *ctx);
EC_POINT *EC_POINT_hex2point(const EC_GROUP *group, const char *hex,
EC_POINT *p, BN_CTX *ctx);
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)>:
const EC_METHOD *EC_POINT_method_of(const EC_POINT *point);
int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
EC_POINT *p,
const BIGNUM *x, const BIGNUM *y,
const BIGNUM *z, BN_CTX *ctx);
int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
const EC_POINT *p,
BIGNUM *x, BIGNUM *y, BIGNUM *z,
BN_CTX *ctx);
int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *p,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *ctx);
int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
const EC_POINT *p,
BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
EC_POINT *p,
const BIGNUM *x, int y_bit,
BN_CTX *ctx);
int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *ctx);
int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
const EC_POINT *p,
BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group,
EC_POINT *p,
const BIGNUM *x, int y_bit,
BN_CTX *ctx);
BIGNUM *EC_POINT_point2bn(const EC_GROUP *group, const EC_POINT *p,
point_conversion_form_t form, BIGNUM *bn,
BN_CTX *ctx);
EC_POINT *EC_POINT_bn2point(const EC_GROUP *group, const BIGNUM *bn,
EC_POINT *p, BN_CTX *ctx);
=head1 DESCRIPTION
An B<EC_POINT> structure represents a point on a curve. A new point is
constructed by calling the function EC_POINT_new() and providing the
B<group> object that the point relates to.
EC_POINT_free() frees the memory associated with the B<EC_POINT>.
if B<point> is NULL nothing is done.
EC_POINT_clear_free() destroys any sensitive data held within the EC_POINT and
then frees its memory. If B<point> is NULL nothing is done.
EC_POINT_copy() copies the point B<src> into B<dst>. Both B<src> and B<dst>
must use the same B<EC_METHOD>.
EC_POINT_dup() creates a new B<EC_POINT> object and copies the content from
B<src> to the newly created B<EC_POINT> object.
EC_POINT_method_of() obtains the B<EC_METHOD> associated with B<point>.
This function was deprecated in OpenSSL 3.0, since EC_METHOD is no longer a
public concept.
A valid point on a curve is the special point at infinity. A point is set to
be at infinity by calling EC_POINT_set_to_infinity().
-The affine co-ordinates for a point describe a point in terms of its x and y
+The affine coordinates for a point describe a point in terms of its x and y
position. The function EC_POINT_set_affine_coordinates() sets the B<x> and B<y>
-co-ordinates for the point B<p> defined over the curve given in B<group>. The
+coordinates for the point B<p> defined over the curve given in B<group>. The
function EC_POINT_get_affine_coordinates() sets B<x> and B<y>, either of which
may be NULL, to the corresponding coordinates of B<p>.
The functions EC_POINT_set_affine_coordinates_GFp() and
EC_POINT_set_affine_coordinates_GF2m() are synonyms for
EC_POINT_set_affine_coordinates(). They are defined for backwards compatibility
only and should not be used.
The functions EC_POINT_get_affine_coordinates_GFp() and
EC_POINT_get_affine_coordinates_GF2m() are synonyms for
EC_POINT_get_affine_coordinates(). They are defined for backwards compatibility
only and should not be used.
-As well as the affine co-ordinates, a point can alternatively be described in
-terms of its Jacobian projective co-ordinates (for Fp curves only). Jacobian
-projective co-ordinates are expressed as three values x, y and z. Working in
-this co-ordinate system provides more efficient point multiplication
-operations. A mapping exists between Jacobian projective co-ordinates and
-affine co-ordinates. A Jacobian projective co-ordinate (x, y, z) can be written
-as an affine co-ordinate as (x/(z^2), y/(z^3)). Conversion to Jacobian
-projective from affine co-ordinates is simple. The co-ordinate (x, y) is mapped
+As well as the affine coordinates, a point can alternatively be described in
+terms of its Jacobian projective coordinates (for Fp curves only). Jacobian
+projective coordinates are expressed as three values x, y and z. Working in
+this coordinate system provides more efficient point multiplication
+operations. A mapping exists between Jacobian projective coordinates and
+affine coordinates. A Jacobian projective coordinate (x, y, z) can be written
+as an affine coordinate as (x/(z^2), y/(z^3)). Conversion to Jacobian
+projective from affine coordinates is simple. The coordinate (x, y) is mapped
to (x, y, 1). Although deprecated in OpenSSL 3.0 and should no longer be used,
-to set or get the projective co-ordinates in older versions use
+to set or get the projective coordinates in older versions use
EC_POINT_set_Jprojective_coordinates_GFp() and
EC_POINT_get_Jprojective_coordinates_GFp() respectively.
Modern versions should instead use EC_POINT_set_affine_coordinates() and
EC_POINT_get_affine_coordinates(), performing the conversion manually using the
above maps in such rare circumstances.
-Points can also be described in terms of their compressed co-ordinates. For a
+Points can also be described in terms of their compressed coordinates. For a
point (x, y), for any given value for x such that the point is on the curve
there will only ever be two possible values for y. Therefore, a point can be set
using the EC_POINT_set_compressed_coordinates() function where B<x> is the x
-co-ordinate and B<y_bit> is a value 0 or 1 to identify which of the two
+coordinate and B<y_bit> is a value 0 or 1 to identify which of the two
possible values for y should be used.
The functions EC_POINT_set_compressed_coordinates_GFp() and
EC_POINT_set_compressed_coordinates_GF2m() are synonyms for
EC_POINT_set_compressed_coordinates(). They are defined for backwards
compatibility only and should not be used.
In addition B<EC_POINT> can be converted to and from various external
representations. The octet form is the binary encoding of the B<ECPoint>
structure (as defined in RFC5480 and used in certificates and TLS records):
only the content octets are present, the B<OCTET STRING> tag and length are
not included. B<BIGNUM> form is the octet form interpreted as a big endian
integer converted to a B<BIGNUM> structure. Hexadecimal form is the octet
form converted to a NULL terminated character string where each character
is one of the printable values 0-9 or A-F (or a-f).
The functions EC_POINT_point2oct(), EC_POINT_oct2point(), EC_POINT_point2bn(),
EC_POINT_bn2point(), EC_POINT_point2hex() and EC_POINT_hex2point() convert from
and to EC_POINTs for the formats: octet, BIGNUM and hexadecimal respectively.
The function EC_POINT_point2oct() encodes the given curve point B<p> as an
octet string into the buffer B<buf> of size B<len>, using the specified
conversion form B<form>.
The encoding conforms with Sec. 2.3.3 of the SECG SEC 1 ("Elliptic Curve
Cryptography") standard.
Similarly the function EC_POINT_oct2point() decodes a curve point into B<p> from
the octet string contained in the given buffer B<buf> of size B<len>, conforming
to Sec. 2.3.4 of the SECG SEC 1 ("Elliptic Curve Cryptography") standard.
The functions EC_POINT_point2hex() and EC_POINT_point2bn() convert a point B<p>,
respectively, to the hexadecimal or BIGNUM representation of the same
encoding of the function EC_POINT_point2oct().
Vice versa, similarly to the function EC_POINT_oct2point(), the functions
EC_POINT_hex2point() and EC_POINT_point2bn() decode the hexadecimal or
BIGNUM representation into the EC_POINT B<p>.
Notice that, according to the standard, the octet string encoding of the point
at infinity for a given curve is fixed to a single octet of value zero and that,
vice versa, a single octet of size zero is decoded as the point at infinity.
The function EC_POINT_point2oct() must be supplied with a buffer long enough to
store the octet form. The return value provides the number of octets stored.
Calling the function with a NULL buffer will not perform the conversion but
will still return the required buffer length.
The function EC_POINT_point2buf() allocates a buffer of suitable length and
writes an EC_POINT to it in octet format. The allocated buffer is written to
B<*pbuf> and its length is returned. The caller must free up the allocated
buffer with a call to OPENSSL_free(). Since the allocated buffer value is
written to B<*pbuf> the B<pbuf> parameter B<MUST NOT> be B<NULL>.
The function EC_POINT_point2hex() will allocate sufficient memory to store the
hexadecimal string. It is the caller's responsibility to free this memory with
a subsequent call to OPENSSL_free().
=head1 RETURN VALUES
EC_POINT_new() and EC_POINT_dup() return the newly allocated EC_POINT or NULL
on error.
The following functions return 1 on success or 0 on error: EC_POINT_copy(),
EC_POINT_set_to_infinity(), EC_POINT_set_Jprojective_coordinates_GFp(),
EC_POINT_get_Jprojective_coordinates_GFp(),
EC_POINT_set_affine_coordinates_GFp(), EC_POINT_get_affine_coordinates_GFp(),
EC_POINT_set_compressed_coordinates_GFp(),
EC_POINT_set_affine_coordinates_GF2m(), EC_POINT_get_affine_coordinates_GF2m(),
EC_POINT_set_compressed_coordinates_GF2m() and EC_POINT_oct2point().
EC_POINT_method_of returns the EC_METHOD associated with the supplied EC_POINT.
EC_POINT_point2oct() and EC_POINT_point2buf() return the length of the required
buffer or 0 on error.
EC_POINT_point2bn() returns the pointer to the BIGNUM supplied, or NULL on
error.
EC_POINT_bn2point() returns the pointer to the EC_POINT supplied, or NULL on
error.
EC_POINT_point2hex() returns a pointer to the hex string, or NULL on error.
EC_POINT_hex2point() returns the pointer to the EC_POINT supplied, or NULL on
error.
=head1 SEE ALSO
L<crypto(7)>, L<EC_GROUP_new(3)>, L<EC_GROUP_copy(3)>,
L<EC_POINT_add(3)>, L<EC_KEY_new(3)>,
L<EC_GFp_simple_method(3)>, L<d2i_ECPKParameters(3)>
=head1 HISTORY
EC_POINT_method_of(),
EC_POINT_set_Jprojective_coordinates_GFp(),
EC_POINT_get_Jprojective_coordinates_GFp(),
EC_POINT_set_affine_coordinates_GFp(), EC_POINT_get_affine_coordinates_GFp(),
EC_POINT_set_compressed_coordinates_GFp(),
EC_POINT_set_affine_coordinates_GF2m(), EC_POINT_get_affine_coordinates_GF2m(),
EC_POINT_set_compressed_coordinates_GF2m(),
EC_POINT_point2bn(), and EC_POINT_bn2point() were deprecated in OpenSSL 3.0.
B<EC_POINT_set_affine_coordinates>, B<EC_POINT_get_affine_coordinates>,
and B<EC_POINT_set_compressed_coordinates> were
added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-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/doc/man3/EVP_EncryptInit.pod b/doc/man3/EVP_EncryptInit.pod
index 7d7db3c9f708..e469f28a7b54 100644
--- a/doc/man3/EVP_EncryptInit.pod
+++ b/doc/man3/EVP_EncryptInit.pod
@@ -1,1737 +1,1737 @@
=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.
=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.
=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>. 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, I<out> should contain sufficient room for the operation being performed.
The actual number of bytes written is placed in I<outl>. It also
checks if I<in> and I<out> are partially overlapping, and if they are
0 is returned to indicate failure.
If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts
the "final" data, that is any data that remains in a partial block.
It uses standard block padding (aka PKCS padding) as described in
the NOTES section, below. The encrypted
final data is written to 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 retreive 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
-"tlsaadpad" (B<OSSL_CIPHER_PARAM_AEAD_TLS1_AAD>)
+"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 the amount of encrypted / decrypted bytes, or -1
on failure if the flag B<EVP_CIPH_FLAG_CUSTOM_CIPHER> is set for the
cipher. 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_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>.
When decrypting, the return value of EVP_DecryptFinal() or EVP_CipherFinal()
indicates whether the operation was successful. If it does not indicate success,
the authentication operation has failed and any output data B<MUST NOT> be used
as it is corrupted.
=head2 GCM and OCB Modes
The following I<ctrl>s are supported in GCM and OCB modes.
=over 4
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)
Sets the IV length. This call can only be made before specifying an IV. If
not called a default IV length is used.
For GCM AES and OCB AES the default is 12 (i.e. 96 bits). For OCB mode the
maximum is 15.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, tag)
Writes C<taglen> bytes of the tag value to the buffer indicated by C<tag>.
This call can only be made when encrypting data and B<after> all data has been
processed (e.g. after an EVP_EncryptFinal() call).
For OCB, C<taglen> must either be 16 or the value previously set via
B<EVP_CTRL_AEAD_SET_TAG>.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, tag)
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.
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-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/doc/man3/EVP_PKEY_set1_RSA.pod b/doc/man3/EVP_PKEY_set1_RSA.pod
index c0366d34fcee..6489b1189403 100644
--- a/doc/man3/EVP_PKEY_set1_RSA.pod
+++ b/doc/man3/EVP_PKEY_set1_RSA.pod
@@ -1,232 +1,238 @@
=pod
=head1 NAME
EVP_PKEY_set1_RSA, EVP_PKEY_set1_DSA, EVP_PKEY_set1_DH, EVP_PKEY_set1_EC_KEY,
EVP_PKEY_get1_RSA, EVP_PKEY_get1_DSA, EVP_PKEY_get1_DH, EVP_PKEY_get1_EC_KEY,
EVP_PKEY_get0_RSA, EVP_PKEY_get0_DSA, EVP_PKEY_get0_DH, EVP_PKEY_get0_EC_KEY,
EVP_PKEY_assign_RSA, EVP_PKEY_assign_DSA, EVP_PKEY_assign_DH,
EVP_PKEY_assign_EC_KEY, EVP_PKEY_assign_POLY1305, EVP_PKEY_assign_SIPHASH,
EVP_PKEY_get0_hmac, EVP_PKEY_get0_poly1305, EVP_PKEY_get0_siphash,
EVP_PKEY_get0, EVP_PKEY_type, EVP_PKEY_get_id, EVP_PKEY_get_base_id,
EVP_PKEY_set1_engine, EVP_PKEY_get0_engine,
EVP_PKEY_id, EVP_PKEY_base_id -
EVP_PKEY assignment functions
=head1 SYNOPSIS
#include <openssl/evp.h>
int EVP_PKEY_get_id(const EVP_PKEY *pkey);
int EVP_PKEY_get_base_id(const EVP_PKEY *pkey);
int EVP_PKEY_type(int type);
#define EVP_PKEY_id EVP_PKEY_get_id
#define EVP_PKEY_base_id EVP_PKEY_get_base_id
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 EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key);
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key);
int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key);
int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key);
RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey);
EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey);
const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len);
const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len);
const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len);
const RSA *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey);
const DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey);
const DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey);
const EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey);
void *EVP_PKEY_get0(const EVP_PKEY *pkey);
int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key);
int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key);
int EVP_PKEY_assign_DH(EVP_PKEY *pkey, DH *key);
int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key);
int EVP_PKEY_assign_POLY1305(EVP_PKEY *pkey, ASN1_OCTET_STRING *key);
int EVP_PKEY_assign_SIPHASH(EVP_PKEY *pkey, ASN1_OCTET_STRING *key);
ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey);
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *engine);
=head1 DESCRIPTION
EVP_PKEY_get_base_id() returns the type of I<pkey>. For example
an RSA key will return B<EVP_PKEY_RSA>.
-EVP_PKEY_get_id() returns the actual OID associated with I<pkey>.
-Historically keys using the same algorithm could use different OIDs.
-For example an RSA key could use the OIDs corresponding to
+EVP_PKEY_get_id() returns the actual NID associated with I<pkey>
+only if the I<pkey> type isn't implemented just in a L<provider(7)>.
+Historically keys using the same algorithm could use different NIDs.
+For example an RSA key could use the NIDs corresponding to
the NIDs B<NID_rsaEncryption> (equivalent to B<EVP_PKEY_RSA>) or
B<NID_rsa> (equivalent to B<EVP_PKEY_RSA2>). The use of
-alternative non-standard OIDs is now rare so B<EVP_PKEY_RSA2> et al are not
+alternative non-standard NIDs is now rare so B<EVP_PKEY_RSA2> et al are not
often seen in practice.
+EVP_PKEY_get_id() returns -1 (B<EVP_PKEY_KEYMGMT>) if the I<pkey> is
+only implemented in a L<provider(7)>.
EVP_PKEY_type() returns the underlying type of the NID I<type>. For example
EVP_PKEY_type(EVP_PKEY_RSA2) will return B<EVP_PKEY_RSA>.
EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH() and
EVP_PKEY_set1_EC_KEY() set the key referenced by I<pkey> to I<key>. These
functions are deprecated. Applications should instead use
L<EVP_PKEY_fromdata(3)>.
EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(),
EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305() and
EVP_PKEY_assign_SIPHASH() set the referenced key to I<key> however these use
the supplied I<key> internally and so I<key> will be freed when the parent
I<pkey> is freed. These macros are deprecated. Applications should instead read
an EVP_PKEY directly using the OSSL_DECODER APIs (see
L<OSSL_DECODER_CTX_new_for_pkey(3)>), or construct an EVP_PKEY from data using
L<EVP_PKEY_fromdata(3)>.
EVP_PKEY_get1_RSA(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and
EVP_PKEY_get1_EC_KEY() return the referenced key in I<pkey> or NULL if the
key is not of the correct type. The returned key must be freed after use.
These functions are deprecated. Applications should instead use the EVP_PKEY
directly where possible. If access to the low level key parameters is required
then applications should use L<EVP_PKEY_get_params(3)> and other similar
functions. To write an EVP_PKEY out use the OSSL_ENCODER APIs (see
L<OSSL_ENCODER_CTX_new_for_pkey(3)>).
EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305(), EVP_PKEY_get0_siphash(),
EVP_PKEY_get0_RSA(), EVP_PKEY_get0_DSA(), EVP_PKEY_get0_DH() and
EVP_PKEY_get0_EC_KEY() return the referenced key in I<pkey> or NULL if the
key is not of the correct type. The reference count of the returned key is
B<not> incremented and so the key must not be freed after use. These functions
are deprecated. Applications should instead use the EVP_PKEY directly where
possible. If access to the low level key parameters is required then
applications should use L<EVP_PKEY_get_params(3)> and other similar functions.
To write an EVP_PKEY out use the OSSL_ENCODER APIs (see
L<OSSL_ENCODER_CTX_new_for_pkey(3)>). EVP_PKEY_get0() returns a pointer to the
legacy key or NULL if the key is not legacy.
Note that if an EVP_PKEY was not constructed using one of the deprecated
functions such as EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH()
or EVP_PKEY_set1_EC_KEY(), or via the similarly named B<EVP_PKEY_assign> macros
described above then the internal key will be managed by a provider (see
L<provider(7)>). In that case the key returned by EVP_PKEY_get1_RSA(),
EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH(), EVP_PKEY_get1_EC_KEY(),
EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305(), EVP_PKEY_get0_siphash(),
EVP_PKEY_get0_RSA(), EVP_PKEY_get0_DSA(), EVP_PKEY_get0_DH() or
EVP_PKEY_get0_EC_KEY() will be a cached copy of the provider's key. Subsequent
updates to the provider's key will not be reflected back in the cached copy, and
updates made by an application to the returned key will not be reflected back in
the provider's key. Subsequent calls to EVP_PKEY_get1_RSA(),
EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and EVP_PKEY_get1_EC_KEY() will always
return the cached copy returned by the first call.
EVP_PKEY_get0_engine() returns a reference to the ENGINE handling I<pkey>. This
function is deprecated. Applications should use providers instead of engines
(see L<provider(7)> for details).
EVP_PKEY_set1_engine() sets the ENGINE handling I<pkey> to I<engine>. It
must be called after the key algorithm and components are set up.
If I<engine> does not include an B<EVP_PKEY_METHOD> for I<pkey> an
error occurs. This function is deprecated. Applications should use providers
instead of engines (see L<provider(7)> for details).
=head1 WARNINGS
The following functions are only reliable with B<EVP_PKEY>s that have
been assigned an internal key with EVP_PKEY_assign_*():
EVP_PKEY_get_id(), EVP_PKEY_get_base_id(), EVP_PKEY_type()
For EVP_PKEY key type checking purposes, L<EVP_PKEY_is_a(3)> is more generic.
+For purposes of retrieving the name of the B<EVP_PKEY> the function
+L<EVP_PKEY_get0_type_name(3)> is more generally useful.
+
The keys returned from the functions EVP_PKEY_get0_RSA(), EVP_PKEY_get0_DSA(),
EVP_PKEY_get0_DH() and EVP_PKEY_get0_EC_KEY() were changed to have a "const"
return type in OpenSSL 3.0. As described above the keys returned may be cached
copies of the key held in a provider. Due to this, and unlike in earlier
versions of OpenSSL, they should be considered read-only copies of the key.
Updates to these keys will not be reflected back in the provider side key. The
EVP_PKEY_get1_RSA(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and
EVP_PKEY_get1_EC_KEY() functions were not changed to have a "const" return type
in order that applications can "free" the return value. However applications
should still consider them as read-only copies.
=head1 NOTES
In accordance with the OpenSSL naming convention the key obtained
from or assigned to the I<pkey> using the B<1> functions must be
freed as well as I<pkey>.
EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(),
EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305()
and EVP_PKEY_assign_SIPHASH() are implemented as macros.
EVP_PKEY_assign_EC_KEY() looks at the curve name id to determine if
the passed B<EC_KEY> is an L<SM2(7)> key, and will set the B<EVP_PKEY>
type to B<EVP_PKEY_SM2> in that case, instead of B<EVP_PKEY_EC>.
Most applications wishing to know a key type will simply call
EVP_PKEY_get_base_id() and will not care about the actual type:
which will be identical in almost all cases.
Previous versions of this document suggested using EVP_PKEY_type(pkey->type)
to determine the type of a key. Since B<EVP_PKEY> is now opaque this
is no longer possible: the equivalent is EVP_PKEY_get_base_id(pkey).
EVP_PKEY_set1_engine() is typically used by an ENGINE returning an HSM
key as part of its routine to load a private key.
=head1 RETURN VALUES
EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH() and
EVP_PKEY_set1_EC_KEY() return 1 for success or 0 for failure.
EVP_PKEY_get1_RSA(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and
EVP_PKEY_get1_EC_KEY() return the referenced key or NULL if
an error occurred.
EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(),
EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305()
and EVP_PKEY_assign_SIPHASH() return 1 for success and 0 for failure.
EVP_PKEY_get_base_id(), EVP_PKEY_get_id() and EVP_PKEY_type() return a key
type or B<NID_undef> (equivalently B<EVP_PKEY_NONE>) on error.
EVP_PKEY_set1_engine() returns 1 for success and 0 for failure.
=head1 SEE ALSO
L<EVP_PKEY_new(3)>, L<SM2(7)>
=head1 HISTORY
The EVP_PKEY_id() and EVP_PKEY_base_id() functions were renamed to
include C<get> in their names in OpenSSL 3.0, respectively. The old names
are kept as non-deprecated alias macros.
EVP_PKEY_set1_RSA, EVP_PKEY_set1_DSA, EVP_PKEY_set1_DH, EVP_PKEY_set1_EC_KEY,
EVP_PKEY_get1_RSA, EVP_PKEY_get1_DSA, EVP_PKEY_get1_DH, EVP_PKEY_get1_EC_KEY,
EVP_PKEY_get0_RSA, EVP_PKEY_get0_DSA, EVP_PKEY_get0_DH, EVP_PKEY_get0_EC_KEY,
EVP_PKEY_assign_RSA, EVP_PKEY_assign_DSA, EVP_PKEY_assign_DH,
EVP_PKEY_assign_EC_KEY, EVP_PKEY_assign_POLY1305, EVP_PKEY_assign_SIPHASH,
EVP_PKEY_get0_hmac, EVP_PKEY_get0_poly1305, EVP_PKEY_get0_siphash,
EVP_PKEY_set1_engine and EVP_PKEY_get0_engine were deprecated in OpenSSL 3.0.
The return value from EVP_PKEY_get0_RSA, EVP_PKEY_get0_DSA, EVP_PKEY_get0_DH,
EVP_PKEY_get0_EC_KEY were made const in OpenSSL 3.0.
The function EVP_PKEY_set_alias_type() was previously documented on this page.
It was removed in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_RAND.pod b/doc/man3/EVP_RAND.pod
index a4d72b70432f..11ea807cc330 100644
--- a/doc/man3/EVP_RAND.pod
+++ b/doc/man3/EVP_RAND.pod
@@ -1,404 +1,416 @@
=pod
=head1 NAME
EVP_RAND, EVP_RAND_fetch, EVP_RAND_free, EVP_RAND_up_ref, EVP_RAND_CTX,
EVP_RAND_CTX_new, EVP_RAND_CTX_free, EVP_RAND_instantiate,
EVP_RAND_uninstantiate, EVP_RAND_generate, EVP_RAND_reseed, EVP_RAND_nonce,
EVP_RAND_enable_locking, EVP_RAND_verify_zeroization, EVP_RAND_get_strength,
EVP_RAND_get_state,
EVP_RAND_get0_provider, EVP_RAND_CTX_get0_rand, EVP_RAND_is_a,
EVP_RAND_get0_name, EVP_RAND_names_do_all,
EVP_RAND_get0_description,
EVP_RAND_CTX_get_params,
EVP_RAND_CTX_set_params, EVP_RAND_do_all_provided, EVP_RAND_get_params,
EVP_RAND_gettable_ctx_params, EVP_RAND_settable_ctx_params,
EVP_RAND_CTX_gettable_params, EVP_RAND_CTX_settable_params,
EVP_RAND_gettable_params, EVP_RAND_STATE_UNINITIALISED, EVP_RAND_STATE_READY,
EVP_RAND_STATE_ERROR - EVP RAND routines
=head1 SYNOPSIS
#include <openssl/evp.h>
typedef struct evp_rand_st EVP_RAND;
typedef struct evp_rand_ctx_st EVP_RAND_CTX;
EVP_RAND *EVP_RAND_fetch(OSSL_LIB_CTX *libctx, const char *algorithm,
const char *properties);
int EVP_RAND_up_ref(EVP_RAND *rand);
void EVP_RAND_free(EVP_RAND *rand);
EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent);
void EVP_RAND_CTX_free(EVP_RAND_CTX *ctx);
EVP_RAND *EVP_RAND_CTX_get0_rand(EVP_RAND_CTX *ctx);
int EVP_RAND_get_params(EVP_RAND *rand, OSSL_PARAM params[]);
int EVP_RAND_CTX_get_params(EVP_RAND_CTX *ctx, OSSL_PARAM params[]);
int EVP_RAND_CTX_set_params(EVP_RAND_CTX *ctx, const OSSL_PARAM params[]);
const OSSL_PARAM *EVP_RAND_gettable_params(const EVP_RAND *rand);
const OSSL_PARAM *EVP_RAND_gettable_ctx_params(const EVP_RAND *rand);
const OSSL_PARAM *EVP_RAND_settable_ctx_params(const EVP_RAND *rand);
const OSSL_PARAM *EVP_RAND_CTX_gettable_params(EVP_RAND_CTX *ctx);
const OSSL_PARAM *EVP_RAND_CTX_settable_params(EVP_RAND_CTX *ctx);
const char *EVP_RAND_get0_name(const EVP_RAND *rand);
const char *EVP_RAND_get0_description(const EVP_RAND *rand);
int EVP_RAND_is_a(const EVP_RAND *rand, const char *name);
const OSSL_PROVIDER *EVP_RAND_get0_provider(const EVP_RAND *rand);
void EVP_RAND_do_all_provided(OSSL_LIB_CTX *libctx,
void (*fn)(EVP_RAND *rand, void *arg),
void *arg);
int EVP_RAND_names_do_all(const EVP_RAND *rand,
void (*fn)(const char *name, void *data),
void *data);
int EVP_RAND_instantiate(EVP_RAND_CTX *ctx, unsigned int strength,
int prediction_resistance,
const unsigned char *pstr, size_t pstr_len,
const OSSL_PARAM params[]);
int EVP_RAND_uninstantiate(EVP_RAND_CTX *ctx);
int EVP_RAND_generate(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen,
unsigned int strength, int prediction_resistance,
const unsigned char *addin, size_t addin_len);
int EVP_RAND_reseed(EVP_RAND_CTX *ctx, int prediction_resistance,
const unsigned char *ent, size_t ent_len,
const unsigned char *addin, size_t addin_len);
int EVP_RAND_nonce(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen);
int EVP_RAND_enable_locking(EVP_RAND_CTX *ctx);
int EVP_RAND_verify_zeroization(EVP_RAND_CTX *ctx);
unsigned int EVP_RAND_get_strength(EVP_RAND_CTX *ctx);
int EVP_RAND_get_state(EVP_RAND_CTX *ctx);
#define EVP_RAND_STATE_UNINITIALISED 0
#define EVP_RAND_STATE_READY 1
#define EVP_RAND_STATE_ERROR 2
=head1 DESCRIPTION
The EVP RAND routines are a high-level interface to random number generators
both deterministic and not.
If you just want to generate random bytes then you don't need to use
these functions: just call RAND_bytes() or RAND_priv_bytes().
If you want to do more, these calls should be used instead of the older
RAND and RAND_DRBG functions.
After creating a B<EVP_RAND_CTX> for the required algorithm using
EVP_RAND_CTX_new(), inputs to the algorithm are supplied either by
passing them as part of the EVP_RAND_instantiate() call or using calls to
EVP_RAND_CTX_set_params() before calling EVP_RAND_instantiate(). Finally,
call EVP_RAND_generate() to produce cryptographically secure random bytes.
=head2 Types
B<EVP_RAND> is a type that holds the implementation of a RAND.
B<EVP_RAND_CTX> is a context type that holds the algorithm inputs.
B<EVP_RAND_CTX> structures are reference counted.
=head2 Algorithm implementation fetching
EVP_RAND_fetch() fetches an implementation of a RAND I<algorithm>, given
a library context I<libctx> and a set of I<properties>.
See L<crypto(7)/ALGORITHM FETCHING> for further information.
The returned value must eventually be freed with
L<EVP_RAND_free(3)>.
EVP_RAND_up_ref() increments the reference count of an already fetched
RAND.
EVP_RAND_free() frees a fetched algorithm.
NULL is a valid parameter, for which this function is a no-op.
=head2 Context manipulation functions
EVP_RAND_CTX_new() creates a new context for the RAND implementation I<rand>.
If not NULL, I<parent> specifies the seed source for this implementation.
Not all random number generators need to have a seed source specified.
If a parent is required, a NULL I<parent> will utilise the operating
system entropy sources.
It is recommended to minimise the number of random number generators that
rely on the operating system for their randomness because this is often scarce.
EVP_RAND_CTX_free() frees up the context I<ctx>. If I<ctx> is NULL, nothing
is done.
EVP_RAND_CTX_get0_rand() returns the B<EVP_RAND> associated with the context
I<ctx>.
=head2 Random Number Generator Functions
EVP_RAND_instantiate() processes any parameters in I<params> and
then instantiates the RAND I<ctx> with a minimum security strength
of <strength> and personalisation string I<pstr> of length <pstr_len>.
If I<prediction_resistance> is specified, fresh entropy from a live source
will be sought. This call operates as per NIST SP 800-90A and SP 800-90C.
EVP_RAND_uninstantiate() uninstantiates the RAND I<ctx> as per
NIST SP 800-90A and SP 800-90C. Subsequent to this call, the RAND cannot
be used to generate bytes. It can only be freed or instantiated again.
EVP_RAND_generate() produces random bytes from the RAND I<ctx> with the
additional input I<addin> of length I<addin_len>. The bytes
produced will meet the security I<strength>.
If I<prediction_resistance> is specified, fresh entropy from a live source
will be sought. This call operates as per NIST SP 800-90A and SP 800-90C.
EVP_RAND_reseed() reseeds the RAND with new entropy.
Entropy I<ent> of length I<ent_len> bytes can be supplied as can additional
input I<addin> of length I<addin_len> bytes. In the FIPS provider, both are
treated as additional input as per NIST SP-800-90Ar1, Sections 9.1 and 9.2.
Additional seed material is also drawn from the RAND's parent or the
operating system. If I<prediction_resistance> is specified, fresh entropy
from a live source will be sought. This call operates as per NIST SP 800-90A
and SP 800-90C.
EVP_RAND_nonce() creates a nonce in I<out> of maximum length I<outlen>
bytes from the RAND I<ctx>. The function returns the length of the generated
nonce. If I<out> is NULL, the length is still returned but no generation
takes place. This allows a caller to dynamically allocate a buffer of the
appropriate size.
EVP_RAND_enable_locking() enables locking for the RAND I<ctx> and all of
its parents. After this I<ctx> will operate in a thread safe manner, albeit
more slowly. This function is not itself thread safe if called with the same
I<ctx> from multiple threads. Typically locking should be enabled before a
I<ctx> is shared across multiple threads.
EVP_RAND_get_params() retrieves details about the implementation
I<rand>.
The set of parameters given with I<params> determine exactly what
parameters should be retrieved.
Note that a parameter that is unknown in the underlying context is
simply ignored.
EVP_RAND_CTX_get_params() retrieves chosen parameters, given the
context I<ctx> and its underlying context.
The set of parameters given with I<params> determine exactly what
parameters should be retrieved.
Note that a parameter that is unknown in the underlying context is
simply ignored.
EVP_RAND_CTX_set_params() passes chosen parameters to the underlying
context, given a context I<ctx>.
The set of parameters given with I<params> determine exactly what
parameters are passed down.
Note that a parameter that is unknown in the underlying context is
simply ignored.
Also, what happens when a needed parameter isn't passed down is
defined by the implementation.
EVP_RAND_gettable_params() returns an L<OSSL_PARAM(3)> array that describes
the retrievable and settable parameters. EVP_RAND_gettable_params() returns
parameters that can be used with EVP_RAND_get_params().
EVP_RAND_gettable_ctx_params() and EVP_RAND_CTX_gettable_params() return
constant L<OSSL_PARAM(3)> arrays that describe the retrievable parameters that
can be used with EVP_RAND_CTX_get_params(). EVP_RAND_gettable_ctx_params()
returns the parameters that can be retrieved from the algorithm, whereas
EVP_RAND_CTX_gettable_params() returns the parameters that can be retrieved
in the context's current state.
EVP_RAND_settable_ctx_params() and EVP_RAND_CTX_settable_params() return
constant L<OSSL_PARAM(3)> arrays that describe the settable parameters that
can be used with EVP_RAND_CTX_set_params(). EVP_RAND_settable_ctx_params()
returns the parameters that can be retrieved from the algorithm, whereas
EVP_RAND_CTX_settable_params() returns the parameters that can be retrieved
in the context's current state.
=head2 Information functions
EVP_RAND_get_strength() returns the security strength of the RAND I<ctx>.
EVP_RAND_get_state() returns the current state of the RAND I<ctx>.
States defined by the OpenSSL RNGs are:
=over 4
=item *
EVP_RAND_STATE_UNINITIALISED: this RNG is currently uninitialised.
The instantiate call will change this to the ready state.
=item *
EVP_RAND_STATE_READY: this RNG is currently ready to generate output.
=item *
EVP_RAND_STATE_ERROR: this RNG is in an error state.
=back
EVP_RAND_is_a() returns 1 if I<rand> is an implementation of an
algorithm that's identifiable with I<name>, otherwise 0.
EVP_RAND_get0_provider() returns the provider that holds the implementation
of the given I<rand>.
EVP_RAND_do_all_provided() traverses all RAND 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.
EVP_RAND_get0_name() returns the canonical name of I<rand>.
EVP_RAND_names_do_all() traverses all names for I<rand>, and calls
I<fn> with each name and I<data>.
EVP_RAND_get0_description() returns a description of the rand, meant for
display and human consumption. The description is at the discretion of
the rand implementation.
EVP_RAND_verify_zeroization() confirms if the internal DRBG state is
currently zeroed. This is used by the FIPS provider to support the mandatory
self tests.
=head1 PARAMETERS
The standard parameter names are:
=over 4
=item "state" (B<OSSL_RAND_PARAM_STATE>) <integer>
Returns the state of the random number generator.
=item "strength" (B<OSSL_RAND_PARAM_STRENGTH>) <unsigned integer>
Returns the bit strength of the random number generator.
=back
For rands that are also deterministic random bit generators (DRBGs), these
additional parameters are recognised. Not all
parameters are relevant to, or are understood by all DRBG rands:
=over 4
=item "reseed_requests" (B<OSSL_DRBG_PARAM_RESEED_REQUESTS>) <unsigned integer>
Reads or set the number of generate requests before reseeding the
associated RAND ctx.
=item "reseed_time_interval" (B<OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL>) <integer>
Reads or set the number of elapsed seconds before reseeding the
associated RAND ctx.
=item "max_request" (B<OSSL_DRBG_PARAM_RESEED_REQUESTS>) <unsigned integer>
Specifies the maximum number of bytes that can be generated in a single
call to OSSL_FUNC_rand_generate.
=item "min_entropylen" (B<OSSL_DRBG_PARAM_MIN_ENTROPYLEN>) <unsigned integer>
=item "max_entropylen" (B<OSSL_DRBG_PARAM_MAX_ENTROPYLEN>) <unsigned integer>
Specify the minimum and maximum number of bytes of random material that
can be used to seed the DRBG.
=item "min_noncelen" (B<OSSL_DRBG_PARAM_MIN_NONCELEN>) <unsigned integer>
=item "max_noncelen" (B<OSSL_DRBG_PARAM_MAX_NONCELEN>) <unsigned integer>
Specify the minimum and maximum number of bytes of nonce that can be used to
seed the DRBG.
=item "max_perslen" (B<OSSL_DRBG_PARAM_MAX_PERSLEN>) <unsigned integer>
=item "max_adinlen" (B<OSSL_DRBG_PARAM_MAX_ADINLEN>) <unsigned integer>
Specify the minimum and maximum number of bytes of personalisation string
that can be used with the DRBG.
=item "reseed_counter" (B<OSSL_DRBG_PARAM_RESEED_COUNTER>) <unsigned integer>
Specifies the number of times the DRBG has been seeded or reseeded.
=item "properties" (B<OSSL_RAND_PARAM_PROPERTIES>) <UTF8 string>
=item "mac" (B<OSSL_RAND_PARAM_MAC>) <UTF8 string>
=item "digest" (B<OSSL_RAND_PARAM_DIGEST>) <UTF8 string>
=item "cipher" (B<OSSL_RAND_PARAM_CIPHER>) <UTF8 string>
For RAND implementations that use an underlying computation MAC, digest or
cipher, these parameters set what the algorithm should be.
The value is always the name of the intended algorithm,
or the properties in the case of B<OSSL_RAND_PARAM_PROPERTIES>.
=back
=head1 NOTES
+The use of a nonzero value for the I<prediction_resistance> argument to
+EVP_RAND_instantiate(), EVP_RAND_generate() or EVP_RAND_reseed() should
+be used sparingly. In the default setup, this will cause all public and
+private DRBGs to be reseeded on next use. Since, by default, public and
+private DRBGs are allocated on a per thread basis, this can result in
+significant overhead for highly multi-threaded applications. For normal
+use-cases, the default "reseed_requests" and "reseed_time_interval"
+thresholds ensure sufficient prediction resistance over time and you
+can reduce those values if you think they are too high. Explicitly
+requesting prediction resistance is intended for more special use-cases
+like generating long-term secrets.
+
An B<EVP_RAND_CTX> needs to have locking enabled if it acts as the parent of
more than one child and the children can be accessed concurrently. This must
be done by explicitly calling EVP_RAND_enable_locking().
The RAND life-cycle is described in L<life_cycle-rand(7)>. In the future,
the transitions described there will be enforced. When this is done, it will
not be considered a breaking change to the API.
=head1 RETURN VALUES
EVP_RAND_fetch() returns a pointer to a newly fetched B<EVP_RAND>, or
NULL if allocation failed.
EVP_RAND_get0_provider() returns a pointer to the provider for the RAND, or
NULL on error.
EVP_RAND_CTX_get0_rand() returns a pointer to the B<EVP_RAND> associated
with the context.
EVP_RAND_get0_name() returns the name of the random number generation
algorithm.
EVP_RAND_up_ref() returns 1 on success, 0 on error.
EVP_RAND_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.
EVP_RAND_CTX_new() returns either the newly allocated
B<EVP_RAND_CTX> structure or NULL if an error occurred.
EVP_RAND_CTX_free() does not return a value.
EVP_RAND_nonce() returns the length of the nonce.
EVP_RAND_get_strength() returns the strength of the random number generator
in bits.
EVP_RAND_gettable_params(), EVP_RAND_gettable_ctx_params() and
EVP_RAND_settable_ctx_params() return an array of OSSL_PARAMs.
EVP_RAND_verify_zeroization() returns 1 if the internal DRBG state is
currently zeroed, and 0 if not.
The remaining functions return 1 for success and 0 or a negative value for
failure.
=head1 SEE ALSO
L<RAND_bytes(3)>,
L<EVP_RAND-CTR-DRBG(7)>,
L<EVP_RAND-HASH-DRBG(7)>,
L<EVP_RAND-HMAC-DRBG(7)>,
L<EVP_RAND-TEST-RAND(7)>,
L<provider-rand(7)>,
L<life_cycle-rand(7)>
=head1 HISTORY
This functionality was added to OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man3/EVP_aes_128_gcm.pod b/doc/man3/EVP_aes_128_gcm.pod
index 0575901503b2..09cae9912950 100644
--- a/doc/man3/EVP_aes_128_gcm.pod
+++ b/doc/man3/EVP_aes_128_gcm.pod
@@ -1,194 +1,201 @@
=pod
=head1 NAME
EVP_aes_128_cbc,
EVP_aes_192_cbc,
EVP_aes_256_cbc,
EVP_aes_128_cfb,
EVP_aes_192_cfb,
EVP_aes_256_cfb,
EVP_aes_128_cfb1,
EVP_aes_192_cfb1,
EVP_aes_256_cfb1,
EVP_aes_128_cfb8,
EVP_aes_192_cfb8,
EVP_aes_256_cfb8,
EVP_aes_128_cfb128,
EVP_aes_192_cfb128,
EVP_aes_256_cfb128,
EVP_aes_128_ctr,
EVP_aes_192_ctr,
EVP_aes_256_ctr,
EVP_aes_128_ecb,
EVP_aes_192_ecb,
EVP_aes_256_ecb,
EVP_aes_128_ofb,
EVP_aes_192_ofb,
EVP_aes_256_ofb,
EVP_aes_128_cbc_hmac_sha1,
EVP_aes_256_cbc_hmac_sha1,
EVP_aes_128_cbc_hmac_sha256,
EVP_aes_256_cbc_hmac_sha256,
EVP_aes_128_ccm,
EVP_aes_192_ccm,
EVP_aes_256_ccm,
EVP_aes_128_gcm,
EVP_aes_192_gcm,
EVP_aes_256_gcm,
EVP_aes_128_ocb,
EVP_aes_192_ocb,
EVP_aes_256_ocb,
EVP_aes_128_wrap,
EVP_aes_192_wrap,
EVP_aes_256_wrap,
EVP_aes_128_wrap_pad,
EVP_aes_192_wrap_pad,
EVP_aes_256_wrap_pad,
EVP_aes_128_xts,
EVP_aes_256_xts
- EVP AES cipher
=head1 SYNOPSIS
=for openssl generic
#include <openssl/evp.h>
const EVP_CIPHER *EVP_ciphername(void)
I<EVP_ciphername> is used a placeholder for any of the described cipher
functions, such as I<EVP_aes_128_cbc>.
=head1 DESCRIPTION
The AES encryption algorithm for EVP.
=over 4
=item EVP_aes_128_cbc(),
EVP_aes_192_cbc(),
EVP_aes_256_cbc(),
EVP_aes_128_cfb(),
EVP_aes_192_cfb(),
EVP_aes_256_cfb(),
EVP_aes_128_cfb1(),
EVP_aes_192_cfb1(),
EVP_aes_256_cfb1(),
EVP_aes_128_cfb8(),
EVP_aes_192_cfb8(),
EVP_aes_256_cfb8(),
EVP_aes_128_cfb128(),
EVP_aes_192_cfb128(),
EVP_aes_256_cfb128(),
EVP_aes_128_ctr(),
EVP_aes_192_ctr(),
EVP_aes_256_ctr(),
EVP_aes_128_ecb(),
EVP_aes_192_ecb(),
EVP_aes_256_ecb(),
EVP_aes_128_ofb(),
EVP_aes_192_ofb(),
EVP_aes_256_ofb()
AES for 128, 192 and 256 bit keys in the following modes: CBC, CFB with 128-bit
shift, CFB with 1-bit shift, CFB with 8-bit shift, CTR, ECB, and OFB.
=item EVP_aes_128_cbc_hmac_sha1(),
EVP_aes_256_cbc_hmac_sha1()
Authenticated encryption with AES in CBC mode using SHA-1 as HMAC, with keys of
128 and 256 bits length respectively. The authentication tag is 160 bits long.
WARNING: this is not intended for usage outside of TLS and requires calling of
some undocumented ctrl functions. These ciphers do not conform to the EVP AEAD
interface.
=item EVP_aes_128_cbc_hmac_sha256(),
EVP_aes_256_cbc_hmac_sha256()
Authenticated encryption with AES in CBC mode using SHA256 (SHA-2, 256-bits) as
HMAC, with keys of 128 and 256 bits length respectively. The authentication tag
is 256 bits long.
WARNING: this is not intended for usage outside of TLS and requires calling of
some undocumented ctrl functions. These ciphers do not conform to the EVP AEAD
interface.
=item EVP_aes_128_ccm(),
EVP_aes_192_ccm(),
EVP_aes_256_ccm(),
EVP_aes_128_gcm(),
EVP_aes_192_gcm(),
EVP_aes_256_gcm(),
EVP_aes_128_ocb(),
EVP_aes_192_ocb(),
EVP_aes_256_ocb()
AES for 128, 192 and 256 bit keys in CBC-MAC Mode (CCM), Galois Counter Mode
(GCM) and OCB Mode respectively. These ciphers require additional control
operations to function correctly, see the L<EVP_EncryptInit(3)/AEAD Interface>
section for details.
=item EVP_aes_128_wrap(),
EVP_aes_192_wrap(),
EVP_aes_256_wrap(),
EVP_aes_128_wrap_pad(),
EVP_aes_128_wrap(),
EVP_aes_192_wrap(),
EVP_aes_256_wrap(),
EVP_aes_192_wrap_pad(),
EVP_aes_128_wrap(),
EVP_aes_192_wrap(),
EVP_aes_256_wrap(),
EVP_aes_256_wrap_pad()
AES key wrap with 128, 192 and 256 bit keys, as according to RFC 3394 section
2.2.1 ("wrap") and RFC 5649 section 4.1 ("wrap with padding") respectively.
=item EVP_aes_128_xts(),
EVP_aes_256_xts()
AES XTS mode (XTS-AES) is standardized in IEEE Std. 1619-2007 and described in NIST
SP 800-38E. The XTS (XEX-based tweaked-codebook mode with ciphertext stealing)
mode was designed by Prof. Phillip Rogaway of University of California, Davis,
intended for encrypting data on a storage device.
XTS-AES provides confidentiality but not authentication of data. It also
requires a key of double-length for protection of a certain key size.
In particular, XTS-AES-128 (B<EVP_aes_128_xts>) takes input of a 256-bit key to
achieve AES 128-bit security, and XTS-AES-256 (B<EVP_aes_256_xts>) takes input
of a 512-bit key to achieve AES 256-bit security.
The XTS implementation in OpenSSL does not support streaming. That is there must
only be one L<EVP_EncryptUpdate(3)> call per L<EVP_EncryptInit_ex(3)> call (and
similarly with the "Decrypt" functions).
The I<iv> parameter to L<EVP_EncryptInit_ex(3)> or L<EVP_DecryptInit_ex(3)> is
the XTS "tweak" value.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_aria_128_gcm.pod b/doc/man3/EVP_aria_128_gcm.pod
index 6471acb24954..92913652630d 100644
--- a/doc/man3/EVP_aria_128_gcm.pod
+++ b/doc/man3/EVP_aria_128_gcm.pod
@@ -1,117 +1,124 @@
=pod
=head1 NAME
EVP_aria_128_cbc,
EVP_aria_192_cbc,
EVP_aria_256_cbc,
EVP_aria_128_cfb,
EVP_aria_192_cfb,
EVP_aria_256_cfb,
EVP_aria_128_cfb1,
EVP_aria_192_cfb1,
EVP_aria_256_cfb1,
EVP_aria_128_cfb8,
EVP_aria_192_cfb8,
EVP_aria_256_cfb8,
EVP_aria_128_cfb128,
EVP_aria_192_cfb128,
EVP_aria_256_cfb128,
EVP_aria_128_ctr,
EVP_aria_192_ctr,
EVP_aria_256_ctr,
EVP_aria_128_ecb,
EVP_aria_192_ecb,
EVP_aria_256_ecb,
EVP_aria_128_ofb,
EVP_aria_192_ofb,
EVP_aria_256_ofb,
EVP_aria_128_ccm,
EVP_aria_192_ccm,
EVP_aria_256_ccm,
EVP_aria_128_gcm,
EVP_aria_192_gcm,
EVP_aria_256_gcm,
- EVP ARIA cipher
=head1 SYNOPSIS
=for openssl generic
#include <openssl/evp.h>
const EVP_CIPHER *EVP_ciphername(void)
I<EVP_ciphername> is used a placeholder for any of the described cipher
functions, such as I<EVP_aria_128_cbc>.
=head1 DESCRIPTION
The ARIA encryption algorithm for EVP.
=over 4
=item EVP_aria_128_cbc(),
EVP_aria_192_cbc(),
EVP_aria_256_cbc(),
EVP_aria_128_cfb(),
EVP_aria_192_cfb(),
EVP_aria_256_cfb(),
EVP_aria_128_cfb1(),
EVP_aria_192_cfb1(),
EVP_aria_256_cfb1(),
EVP_aria_128_cfb8(),
EVP_aria_192_cfb8(),
EVP_aria_256_cfb8(),
EVP_aria_128_cfb128(),
EVP_aria_192_cfb128(),
EVP_aria_256_cfb128(),
EVP_aria_128_ctr(),
EVP_aria_192_ctr(),
EVP_aria_256_ctr(),
EVP_aria_128_ecb(),
EVP_aria_192_ecb(),
EVP_aria_256_ecb(),
EVP_aria_128_ofb(),
EVP_aria_192_ofb(),
EVP_aria_256_ofb()
ARIA for 128, 192 and 256 bit keys in the following modes: CBC, CFB with
128-bit shift, CFB with 1-bit shift, CFB with 8-bit shift, CTR, ECB and OFB.
=item EVP_aria_128_ccm(),
EVP_aria_192_ccm(),
EVP_aria_256_ccm(),
EVP_aria_128_gcm(),
EVP_aria_192_gcm(),
EVP_aria_256_gcm(),
ARIA for 128, 192 and 256 bit keys in CBC-MAC Mode (CCM) and Galois Counter
Mode (GCM). These ciphers require additional control operations to function
correctly, see the L<EVP_EncryptInit(3)/AEAD Interface> section for details.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_bf_cbc.pod b/doc/man3/EVP_bf_cbc.pod
index 03385620873e..4df98f4bdf47 100644
--- a/doc/man3/EVP_bf_cbc.pod
+++ b/doc/man3/EVP_bf_cbc.pod
@@ -1,61 +1,68 @@
=pod
=head1 NAME
EVP_bf_cbc,
EVP_bf_cfb,
EVP_bf_cfb64,
EVP_bf_ecb,
EVP_bf_ofb
- EVP Blowfish cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_bf_cbc(void);
const EVP_CIPHER *EVP_bf_cfb(void);
const EVP_CIPHER *EVP_bf_cfb64(void);
const EVP_CIPHER *EVP_bf_ecb(void);
const EVP_CIPHER *EVP_bf_ofb(void);
=head1 DESCRIPTION
The Blowfish encryption algorithm for EVP.
This is a variable key length cipher.
=over 4
=item EVP_bf_cbc(),
EVP_bf_cfb(),
EVP_bf_cfb64(),
EVP_bf_ecb(),
EVP_bf_ofb()
Blowfish encryption algorithm in CBC, CFB, ECB and OFB modes respectively.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_blake2b512.pod b/doc/man3/EVP_blake2b512.pod
index 649a29c98717..98e1899f6a93 100644
--- a/doc/man3/EVP_blake2b512.pod
+++ b/doc/man3/EVP_blake2b512.pod
@@ -1,65 +1,70 @@
=pod
=head1 NAME
EVP_blake2b512,
EVP_blake2s256
- BLAKE2 For EVP
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_MD *EVP_blake2b512(void);
const EVP_MD *EVP_blake2s256(void);
=head1 DESCRIPTION
BLAKE2 is an improved version of BLAKE, which was submitted to the NIST SHA-3
algorithm competition. The BLAKE2s and BLAKE2b algorithms are described in
RFC 7693.
=over 4
=item EVP_blake2s256()
The BLAKE2s algorithm that produces a 256-bit output from a given input.
=item EVP_blake2b512()
The BLAKE2b algorithm that produces a 512-bit output from a given input.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_MD_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
+While the BLAKE2b and BLAKE2s algorithms supports a variable length digest,
+this implementation outputs a digest of a fixed length (the maximum length
+supported), which is 512-bits for BLAKE2b and 256-bits for BLAKE2s.
+
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
RFC 7693.
-=head1 NOTES
-
-While the BLAKE2b and BLAKE2s algorithms supports a variable length digest,
-this implementation outputs a digest of a fixed length (the maximum length
-supported), which is 512-bits for BLAKE2b and 256-bits for BLAKE2s.
-
=head1 SEE ALSO
L<evp(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_camellia_128_ecb.pod b/doc/man3/EVP_camellia_128_ecb.pod
index 4a57f79512c4..a6b597156a77 100644
--- a/doc/man3/EVP_camellia_128_ecb.pod
+++ b/doc/man3/EVP_camellia_128_ecb.pod
@@ -1,100 +1,107 @@
=pod
=head1 NAME
EVP_camellia_128_cbc,
EVP_camellia_192_cbc,
EVP_camellia_256_cbc,
EVP_camellia_128_cfb,
EVP_camellia_192_cfb,
EVP_camellia_256_cfb,
EVP_camellia_128_cfb1,
EVP_camellia_192_cfb1,
EVP_camellia_256_cfb1,
EVP_camellia_128_cfb8,
EVP_camellia_192_cfb8,
EVP_camellia_256_cfb8,
EVP_camellia_128_cfb128,
EVP_camellia_192_cfb128,
EVP_camellia_256_cfb128,
EVP_camellia_128_ctr,
EVP_camellia_192_ctr,
EVP_camellia_256_ctr,
EVP_camellia_128_ecb,
EVP_camellia_192_ecb,
EVP_camellia_256_ecb,
EVP_camellia_128_ofb,
EVP_camellia_192_ofb,
EVP_camellia_256_ofb
- EVP Camellia cipher
=head1 SYNOPSIS
=for openssl generic
#include <openssl/evp.h>
const EVP_CIPHER *EVP_ciphername(void)
I<EVP_ciphername> is used a placeholder for any of the described cipher
functions, such as I<EVP_camellia_128_cbc>.
=head1 DESCRIPTION
The Camellia encryption algorithm for EVP.
=over 4
=item EVP_camellia_128_cbc(),
EVP_camellia_192_cbc(),
EVP_camellia_256_cbc(),
EVP_camellia_128_cfb(),
EVP_camellia_192_cfb(),
EVP_camellia_256_cfb(),
EVP_camellia_128_cfb1(),
EVP_camellia_192_cfb1(),
EVP_camellia_256_cfb1(),
EVP_camellia_128_cfb8(),
EVP_camellia_192_cfb8(),
EVP_camellia_256_cfb8(),
EVP_camellia_128_cfb128(),
EVP_camellia_192_cfb128(),
EVP_camellia_256_cfb128(),
EVP_camellia_128_ctr(),
EVP_camellia_192_ctr(),
EVP_camellia_256_ctr(),
EVP_camellia_128_ecb(),
EVP_camellia_192_ecb(),
EVP_camellia_256_ecb(),
EVP_camellia_128_ofb(),
EVP_camellia_192_ofb(),
EVP_camellia_256_ofb()
Camellia for 128, 192 and 256 bit keys in the following modes: CBC, CFB with
128-bit shift, CFB with 1-bit shift, CFB with 8-bit shift, CTR, ECB and OFB.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_cast5_cbc.pod b/doc/man3/EVP_cast5_cbc.pod
index e823a197f959..85ff2ad01488 100644
--- a/doc/man3/EVP_cast5_cbc.pod
+++ b/doc/man3/EVP_cast5_cbc.pod
@@ -1,61 +1,68 @@
=pod
=head1 NAME
EVP_cast5_cbc,
EVP_cast5_cfb,
EVP_cast5_cfb64,
EVP_cast5_ecb,
EVP_cast5_ofb
- EVP CAST cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_cast5_cbc(void);
const EVP_CIPHER *EVP_cast5_cfb(void);
const EVP_CIPHER *EVP_cast5_cfb64(void);
const EVP_CIPHER *EVP_cast5_ecb(void);
const EVP_CIPHER *EVP_cast5_ofb(void);
=head1 DESCRIPTION
The CAST encryption algorithm for EVP.
This is a variable key length cipher.
=over 4
=item EVP_cast5_cbc(),
EVP_cast5_ecb(),
EVP_cast5_cfb(),
EVP_cast5_cfb64(),
EVP_cast5_ofb()
CAST encryption algorithm in CBC, ECB, CFB and OFB modes respectively.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_chacha20.pod b/doc/man3/EVP_chacha20.pod
index 060b1bfc254f..28ab25bf7188 100644
--- a/doc/man3/EVP_chacha20.pod
+++ b/doc/man3/EVP_chacha20.pod
@@ -1,65 +1,72 @@
=pod
=head1 NAME
EVP_chacha20,
EVP_chacha20_poly1305
- EVP ChaCha20 stream cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_chacha20(void);
const EVP_CIPHER *EVP_chacha20_poly1305(void);
=head1 DESCRIPTION
The ChaCha20 stream cipher for EVP.
=over 4
=item EVP_chacha20()
The ChaCha20 stream cipher. The key length is 256 bits, the IV is 128 bits long.
The first 32 bits consists of a counter in little-endian order followed by a 96
bit nonce. For example a nonce of:
000000000000000000000002
With an initial counter of 42 (2a in hex) would be expressed as:
2a000000000000000000000000000002
=item EVP_chacha20_poly1305()
Authenticated encryption with ChaCha20-Poly1305. Like EVP_chacha20(), the key
is 256 bits and the IV is 96 bits. This supports additional authenticated data
(AAD) and produces a 128-bit authentication tag. See the
L<EVP_EncryptInit(3)/AEAD Interface> section for more information.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_des_cbc.pod b/doc/man3/EVP_des_cbc.pod
index fe9d5e6a0e07..501216cd6d77 100644
--- a/doc/man3/EVP_des_cbc.pod
+++ b/doc/man3/EVP_des_cbc.pod
@@ -1,110 +1,117 @@
=pod
=head1 NAME
EVP_des_cbc,
EVP_des_cfb,
EVP_des_cfb1,
EVP_des_cfb8,
EVP_des_cfb64,
EVP_des_ecb,
EVP_des_ofb,
EVP_des_ede,
EVP_des_ede_cbc,
EVP_des_ede_cfb,
EVP_des_ede_cfb64,
EVP_des_ede_ecb,
EVP_des_ede_ofb,
EVP_des_ede3,
EVP_des_ede3_cbc,
EVP_des_ede3_cfb,
EVP_des_ede3_cfb1,
EVP_des_ede3_cfb8,
EVP_des_ede3_cfb64,
EVP_des_ede3_ecb,
EVP_des_ede3_ofb,
EVP_des_ede3_wrap
- EVP DES cipher
=head1 SYNOPSIS
=for openssl generic
#include <openssl/evp.h>
const EVP_CIPHER *EVP_ciphername(void)
I<EVP_ciphername> is used a placeholder for any of the described cipher
functions, such as I<EVP_des_cbc>.
=head1 DESCRIPTION
The DES encryption algorithm for EVP.
=over 4
=item EVP_des_cbc(),
EVP_des_ecb(),
EVP_des_cfb(),
EVP_des_cfb1(),
EVP_des_cfb8(),
EVP_des_cfb64(),
EVP_des_ofb()
DES in CBC, ECB, CFB with 64-bit shift, CFB with 1-bit shift, CFB with 8-bit
shift and OFB modes.
None of these algorithms are provided by the OpenSSL default provider.
To use them it is necessary to load either the OpenSSL legacy provider or another
implementation.
=item EVP_des_ede(),
EVP_des_ede_cbc(),
EVP_des_ede_cfb(),
EVP_des_ede_cfb64(),
EVP_des_ede_ecb(),
EVP_des_ede_ofb()
Two key triple DES in ECB, CBC, CFB with 64-bit shift and OFB modes.
=item EVP_des_ede3(),
EVP_des_ede3_cbc(),
EVP_des_ede3_cfb(),
EVP_des_ede3_cfb1(),
EVP_des_ede3_cfb8(),
EVP_des_ede3_cfb64(),
EVP_des_ede3_ecb(),
EVP_des_ede3_ofb()
Three-key triple DES in ECB, CBC, CFB with 64-bit shift, CFB with 1-bit shift,
CFB with 8-bit shift and OFB modes.
=item EVP_des_ede3_wrap()
Triple-DES key wrap according to RFC 3217 Section 3.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_desx_cbc.pod b/doc/man3/EVP_desx_cbc.pod
index 01987bf28cfb..fae827192ee9 100644
--- a/doc/man3/EVP_desx_cbc.pod
+++ b/doc/man3/EVP_desx_cbc.pod
@@ -1,54 +1,59 @@
=pod
=head1 NAME
EVP_desx_cbc
- EVP DES-X cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_desx_cbc(void);
=head1 DESCRIPTION
The DES-X encryption algorithm for EVP.
All modes below use a key length of 128 bits and acts on blocks of 128-bits.
=over 4
=item EVP_desx_cbc()
The DES-X algorithm in CBC mode.
This algorithm is not provided by the OpenSSL default provider.
To use it is necessary to load either the OpenSSL legacy provider or another
implementation.
=back
+Developers should be aware of the negative performance implications of
+calling this function multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_idea_cbc.pod b/doc/man3/EVP_idea_cbc.pod
index 2fa5a2925f0f..5a9adaedc446 100644
--- a/doc/man3/EVP_idea_cbc.pod
+++ b/doc/man3/EVP_idea_cbc.pod
@@ -1,59 +1,66 @@
=pod
=head1 NAME
EVP_idea_cbc,
EVP_idea_cfb,
EVP_idea_cfb64,
EVP_idea_ecb,
EVP_idea_ofb
- EVP IDEA cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_idea_cbc(void);
const EVP_CIPHER *EVP_idea_cfb(void);
const EVP_CIPHER *EVP_idea_cfb64(void);
const EVP_CIPHER *EVP_idea_ecb(void);
const EVP_CIPHER *EVP_idea_ofb(void);
=head1 DESCRIPTION
The IDEA encryption algorithm for EVP.
=over 4
=item EVP_idea_cbc(),
EVP_idea_cfb(),
EVP_idea_cfb64(),
EVP_idea_ecb(),
EVP_idea_ofb()
The IDEA encryption algorithm in CBC, CFB, ECB and OFB modes respectively.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_md2.pod b/doc/man3/EVP_md2.pod
index 420bb1545316..0b473887e01b 100644
--- a/doc/man3/EVP_md2.pod
+++ b/doc/man3/EVP_md2.pod
@@ -1,54 +1,60 @@
=pod
=head1 NAME
EVP_md2
- MD2 For EVP
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_MD *EVP_md2(void);
=head1 DESCRIPTION
MD2 is a cryptographic hash function standardized in RFC 1319 and designed by
Ronald Rivest. This implementation is only available with the legacy provider.
=over 4
=item EVP_md2()
The MD2 algorithm which produces a 128-bit output from a given input.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling this function multiple times and should consider using
+L<EVP_MD_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
IETF RFC 1319.
=head1 SEE ALSO
L<evp(7)>,
L<provider(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_md4.pod b/doc/man3/EVP_md4.pod
index a3d3beaaf83d..baaff9e4eaa2 100644
--- a/doc/man3/EVP_md4.pod
+++ b/doc/man3/EVP_md4.pod
@@ -1,55 +1,61 @@
=pod
=head1 NAME
EVP_md4
- MD4 For EVP
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_MD *EVP_md4(void);
=head1 DESCRIPTION
MD4 is a cryptographic hash function standardized in RFC 1320 and designed by
Ronald Rivest, first published in 1990. This implementation is only available
with the legacy provider.
=over 4
=item EVP_md4()
The MD4 algorithm which produces a 128-bit output from a given input.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling this function multiple times and should consider using
+L<EVP_MD_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
IETF RFC 1320.
=head1 SEE ALSO
L<evp(7)>,
L<provider(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_md5.pod b/doc/man3/EVP_md5.pod
index 9d729601a066..752fdd1f6c37 100644
--- a/doc/man3/EVP_md5.pod
+++ b/doc/man3/EVP_md5.pod
@@ -1,65 +1,71 @@
=pod
=head1 NAME
EVP_md5,
EVP_md5_sha1
- MD5 For EVP
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_MD *EVP_md5(void);
const EVP_MD *EVP_md5_sha1(void);
=head1 DESCRIPTION
MD5 is a cryptographic hash function standardized in RFC 1321 and designed by
Ronald Rivest.
The CMU Software Engineering Institute considers MD5 unsuitable for further
use since its security has been severely compromised.
=over 4
=item EVP_md5()
The MD5 algorithm which produces a 128-bit output from a given input.
=item EVP_md5_sha1()
A hash algorithm of SSL v3 that combines MD5 with SHA-1 as described in RFC
6101.
WARNING: this algorithm is not intended for non-SSL usage.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_MD_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
IETF RFC 1321.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_mdc2.pod b/doc/man3/EVP_mdc2.pod
index 7ebed04c700d..e9de6f3c560a 100644
--- a/doc/man3/EVP_mdc2.pod
+++ b/doc/man3/EVP_mdc2.pod
@@ -1,55 +1,62 @@
=pod
=head1 NAME
EVP_mdc2
- MDC-2 For EVP
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_MD *EVP_mdc2(void);
=head1 DESCRIPTION
MDC-2 (Modification Detection Code 2 or Meyer-Schilling) is a cryptographic
hash function based on a block cipher. This implementation is only available
with the legacy provider.
=over 4
=item EVP_mdc2()
The MDC-2DES algorithm of using MDC-2 with the DES block cipher. It produces a
128-bit output from a given input.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling this function multiple times and should consider using
+L<EVP_MD_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
ISO/IEC 10118-2:2000 Hash-Function 2, with DES as the underlying block cipher.
=head1 SEE ALSO
L<evp(7)>,
L<provider(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_rc2_cbc.pod b/doc/man3/EVP_rc2_cbc.pod
index e6111ff3afc5..bf4a13ba45c1 100644
--- a/doc/man3/EVP_rc2_cbc.pod
+++ b/doc/man3/EVP_rc2_cbc.pod
@@ -1,76 +1,83 @@
=pod
=head1 NAME
EVP_rc2_cbc,
EVP_rc2_cfb,
EVP_rc2_cfb64,
EVP_rc2_ecb,
EVP_rc2_ofb,
EVP_rc2_40_cbc,
EVP_rc2_64_cbc
- EVP RC2 cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_rc2_cbc(void);
const EVP_CIPHER *EVP_rc2_cfb(void);
const EVP_CIPHER *EVP_rc2_cfb64(void);
const EVP_CIPHER *EVP_rc2_ecb(void);
const EVP_CIPHER *EVP_rc2_ofb(void);
const EVP_CIPHER *EVP_rc2_40_cbc(void);
const EVP_CIPHER *EVP_rc2_64_cbc(void);
=head1 DESCRIPTION
The RC2 encryption algorithm for EVP.
=over 4
=item EVP_rc2_cbc(),
EVP_rc2_cfb(),
EVP_rc2_cfb64(),
EVP_rc2_ecb(),
EVP_rc2_ofb()
RC2 encryption algorithm in CBC, CFB, ECB and OFB modes respectively. This is a
variable key length cipher with an additional parameter called "effective key
bits" or "effective key length". By default both are set to 128 bits.
=item EVP_rc2_40_cbc(),
EVP_rc2_64_cbc()
RC2 algorithm in CBC mode with a default key length and effective key length of
40 and 64 bits.
WARNING: these functions are obsolete. Their usage should be replaced with the
EVP_rc2_cbc(), EVP_CIPHER_CTX_set_key_length() and EVP_CIPHER_CTX_ctrl()
functions to set the key length and effective key length.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_rc4.pod b/doc/man3/EVP_rc4.pod
index 9deaab97f82c..f22e88a65214 100644
--- a/doc/man3/EVP_rc4.pod
+++ b/doc/man3/EVP_rc4.pod
@@ -1,67 +1,74 @@
=pod
=head1 NAME
EVP_rc4,
EVP_rc4_40,
EVP_rc4_hmac_md5
- EVP RC4 stream cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_rc4(void);
const EVP_CIPHER *EVP_rc4_40(void);
const EVP_CIPHER *EVP_rc4_hmac_md5(void);
=head1 DESCRIPTION
The RC4 stream cipher for EVP.
=over 4
=item EVP_rc4()
RC4 stream cipher. This is a variable key length cipher with a default key
length of 128 bits.
=item EVP_rc4_40()
RC4 stream cipher with 40 bit key length.
WARNING: this function is obsolete. Its usage should be replaced with the
EVP_rc4() and the EVP_CIPHER_CTX_set_key_length() functions.
=item EVP_rc4_hmac_md5()
Authenticated encryption with the RC4 stream cipher with MD5 as HMAC.
WARNING: this is not intended for usage outside of TLS and requires calling of
some undocumented ctrl functions. These ciphers do not conform to the EVP AEAD
interface.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_rc5_32_12_16_cbc.pod b/doc/man3/EVP_rc5_32_12_16_cbc.pod
index 8ac23b4a9ed1..c177b1845196 100644
--- a/doc/man3/EVP_rc5_32_12_16_cbc.pod
+++ b/doc/man3/EVP_rc5_32_12_16_cbc.pod
@@ -1,81 +1,88 @@
=pod
=head1 NAME
EVP_rc5_32_12_16_cbc,
EVP_rc5_32_12_16_cfb,
EVP_rc5_32_12_16_cfb64,
EVP_rc5_32_12_16_ecb,
EVP_rc5_32_12_16_ofb
- EVP RC5 cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void);
const EVP_CIPHER *EVP_rc5_32_12_16_cfb(void);
const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(void);
const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void);
const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void);
=head1 DESCRIPTION
The RC5 encryption algorithm for EVP.
=over 4
=item EVP_rc5_32_12_16_cbc(),
EVP_rc5_32_12_16_cfb(),
EVP_rc5_32_12_16_cfb64(),
EVP_rc5_32_12_16_ecb(),
EVP_rc5_32_12_16_ofb()
RC5 encryption algorithm in CBC, CFB, ECB and OFB modes respectively. This is a
variable key length cipher with an additional "number of rounds" parameter. By
default the key length is set to 128 bits and 12 rounds. Alternative key lengths
can be set using L<EVP_CIPHER_CTX_set_key_length(3)>. The maximum key length is
2040 bits.
The following rc5 specific I<ctrl>s are supported (see
L<EVP_CIPHER_CTX_ctrl(3)>).
=over 4
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC5_ROUNDS, rounds, NULL)
Sets the number of rounds to B<rounds>. This must be one of RC5_8_ROUNDS,
RC5_12_ROUNDS or RC5_16_ROUNDS.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GET_RC5_ROUNDS, 0, &rounds)
Stores the number of rounds currently configured in B<*rounds> where B<*rounds>
is an int.
=back
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_ripemd160.pod b/doc/man3/EVP_ripemd160.pod
index e559b0344942..6ad2d3e01869 100644
--- a/doc/man3/EVP_ripemd160.pod
+++ b/doc/man3/EVP_ripemd160.pod
@@ -1,54 +1,61 @@
=pod
=head1 NAME
EVP_ripemd160
- RIPEMD160 For EVP
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_MD *EVP_ripemd160(void);
=head1 DESCRIPTION
RIPEMD-160 is a cryptographic hash function first published in 1996 belonging
to the RIPEMD family (RACE Integrity Primitives Evaluation Message Digest).
This implementation is only available with the legacy provider.
=over 4
=item EVP_ripemd160()
The RIPEMD-160 algorithm which produces a 160-bit output from a given input.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling this function multiple times and should consider using
+L<EVP_MD_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
ISO/IEC 10118-3:2016 Dedicated Hash-Function 1 (RIPEMD-160).
=head1 SEE ALSO
L<evp(7)>,
L<provider(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_seed_cbc.pod b/doc/man3/EVP_seed_cbc.pod
index eef7dd540db2..010607e57405 100644
--- a/doc/man3/EVP_seed_cbc.pod
+++ b/doc/man3/EVP_seed_cbc.pod
@@ -1,61 +1,68 @@
=pod
=head1 NAME
EVP_seed_cbc,
EVP_seed_cfb,
EVP_seed_cfb128,
EVP_seed_ecb,
EVP_seed_ofb
- EVP SEED cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_seed_cbc(void);
const EVP_CIPHER *EVP_seed_cfb(void);
const EVP_CIPHER *EVP_seed_cfb128(void);
const EVP_CIPHER *EVP_seed_ecb(void);
const EVP_CIPHER *EVP_seed_ofb(void);
=head1 DESCRIPTION
The SEED encryption algorithm for EVP.
All modes below use a key length of 128 bits and acts on blocks of 128-bits.
=over 4
=item EVP_seed_cbc(),
EVP_seed_cfb(),
EVP_seed_cfb128(),
EVP_seed_ecb(),
EVP_seed_ofb()
The SEED encryption algorithm in CBC, CFB, ECB and OFB modes respectively.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_sha1.pod b/doc/man3/EVP_sha1.pod
index f3e9e8d4fa19..264ddd1addb7 100644
--- a/doc/man3/EVP_sha1.pod
+++ b/doc/man3/EVP_sha1.pod
@@ -1,54 +1,60 @@
=pod
=head1 NAME
EVP_sha1
- SHA-1 For EVP
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_MD *EVP_sha1(void);
=head1 DESCRIPTION
SHA-1 (Secure Hash Algorithm 1) is a cryptographic hash function standardized
in NIST FIPS 180-4. The algorithm was designed by the United States National
Security Agency and initially published in 1995.
=over 4
=item EVP_sha1()
The SHA-1 algorithm which produces a 160-bit output from a given input.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling this function multiple times and should consider using
+L<EVP_MD_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
NIST FIPS 180-4.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_sha224.pod b/doc/man3/EVP_sha224.pod
index 97881b54635c..7a50cf9b6c3f 100644
--- a/doc/man3/EVP_sha224.pod
+++ b/doc/man3/EVP_sha224.pod
@@ -1,74 +1,80 @@
=pod
=head1 NAME
EVP_sha224,
EVP_sha256,
EVP_sha512_224,
EVP_sha512_256,
EVP_sha384,
EVP_sha512
- SHA-2 For EVP
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_MD *EVP_sha224(void);
const EVP_MD *EVP_sha256(void);
const EVP_MD *EVP_sha512_224(void);
const EVP_MD *EVP_sha512_256(void);
const EVP_MD *EVP_sha384(void);
const EVP_MD *EVP_sha512(void);
=head1 DESCRIPTION
SHA-2 (Secure Hash Algorithm 2) is a family of cryptographic hash functions
standardized in NIST FIPS 180-4, first published in 2001.
=over 4
=item EVP_sha224(),
EVP_sha256(),
EVP_sha512_224,
EVP_sha512_256,
EVP_sha384(),
EVP_sha512()
The SHA-2 SHA-224, SHA-256, SHA-512/224, SHA512/256, SHA-384 and SHA-512
algorithms, which generate 224, 256, 224, 256, 384 and 512 bits
respectively of output from a given input.
The two algorithms: SHA-512/224 and SHA512/256 are truncated forms of the
SHA-512 algorithm. They are distinct from SHA-224 and SHA-256 even though
their outputs are of the same size.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_MD_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
NIST FIPS 180-4.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_sha3_224.pod b/doc/man3/EVP_sha3_224.pod
index 4c349f55d32f..5bb9ae1b89e5 100644
--- a/doc/man3/EVP_sha3_224.pod
+++ b/doc/man3/EVP_sha3_224.pod
@@ -1,79 +1,85 @@
=pod
=head1 NAME
EVP_sha3_224,
EVP_sha3_256,
EVP_sha3_384,
EVP_sha3_512,
EVP_shake128,
EVP_shake256
- SHA-3 For EVP
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_MD *EVP_sha3_224(void);
const EVP_MD *EVP_sha3_256(void);
const EVP_MD *EVP_sha3_384(void);
const EVP_MD *EVP_sha3_512(void);
const EVP_MD *EVP_shake128(void);
const EVP_MD *EVP_shake256(void);
=head1 DESCRIPTION
SHA-3 (Secure Hash Algorithm 3) is a family of cryptographic hash functions
standardized in NIST FIPS 202, first published in 2015. It is based on the
Keccak algorithm.
=over 4
=item EVP_sha3_224(),
EVP_sha3_256(),
EVP_sha3_384(),
EVP_sha3_512()
The SHA-3 SHA-3-224, SHA-3-256, SHA-3-384, and SHA-3-512 algorithms
respectively. They produce 224, 256, 384 and 512 bits of output from a given
input.
=item EVP_shake128(),
EVP_shake256()
The SHAKE-128 and SHAKE-256 Extendable Output Functions (XOF) that can generate
a variable hash length.
Specifically, B<EVP_shake128> provides an overall security of 128 bits, while
B<EVP_shake256> provides that of 256 bits.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_MD_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
NIST FIPS 202.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_sm3.pod b/doc/man3/EVP_sm3.pod
index 96997b1128ae..4e8112dc0afe 100644
--- a/doc/man3/EVP_sm3.pod
+++ b/doc/man3/EVP_sm3.pod
@@ -1,54 +1,60 @@
=pod
=head1 NAME
EVP_sm3
- SM3 for EVP
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_MD *EVP_sm3(void);
=head1 DESCRIPTION
SM3 is a cryptographic hash function with a 256-bit output, defined in GB/T
32905-2016.
=over 4
=item EVP_sm3()
The SM3 hash function.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling this function multiple times and should consider using
+L<EVP_MD_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
GB/T 32905-2016 and GM/T 0004-2012.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved.
Copyright 2017 Ribose 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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_sm4_cbc.pod b/doc/man3/EVP_sm4_cbc.pod
index 51df4435bc08..b67ade549968 100644
--- a/doc/man3/EVP_sm4_cbc.pod
+++ b/doc/man3/EVP_sm4_cbc.pod
@@ -1,67 +1,74 @@
=pod
=head1 NAME
EVP_sm4_cbc,
EVP_sm4_ecb,
EVP_sm4_cfb,
EVP_sm4_cfb128,
EVP_sm4_ofb,
EVP_sm4_ctr
- EVP SM4 cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_sm4_cbc(void);
const EVP_CIPHER *EVP_sm4_ecb(void);
const EVP_CIPHER *EVP_sm4_cfb(void);
const EVP_CIPHER *EVP_sm4_cfb128(void);
const EVP_CIPHER *EVP_sm4_ofb(void);
const EVP_CIPHER *EVP_sm4_ctr(void);
=head1 DESCRIPTION
The SM4 blockcipher (GB/T 32907-2016) for EVP.
All modes below use a key length of 128 bits and acts on blocks of 128 bits.
=over 4
=item EVP_sm4_cbc(),
EVP_sm4_ecb(),
EVP_sm4_cfb(),
EVP_sm4_cfb128(),
EVP_sm4_ofb(),
EVP_sm4_ctr()
The SM4 blockcipher with a 128-bit key in CBC, ECB, CFB, OFB and CTR modes
respectively.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling these functions multiple times and should consider using
+L<EVP_CIPHER_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
+
=head1 RETURN VALUES
These functions return a B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved.
Copyright 2017 Ribose 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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_whirlpool.pod b/doc/man3/EVP_whirlpool.pod
index 3aaf1d50add4..a9826e290a42 100644
--- a/doc/man3/EVP_whirlpool.pod
+++ b/doc/man3/EVP_whirlpool.pod
@@ -1,56 +1,62 @@
=pod
=head1 NAME
EVP_whirlpool
- WHIRLPOOL For EVP
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_MD *EVP_whirlpool(void);
=head1 DESCRIPTION
WHIRLPOOL is a cryptographic hash function standardized in ISO/IEC 10118-3:2004
designed by Vincent Rijmen and Paulo S. L. M. Barreto. This implementation is
only available with the legacy provider.
=over 4
=item EVP_whirlpool()
The WHIRLPOOL algorithm that produces a message digest of 512-bits from a given
input.
=back
+=head1 NOTES
+
+Developers should be aware of the negative performance implications of
+calling this function multiple times and should consider using
+L<EVP_MD_fetch(3)> instead.
+See L<crypto(7)/Performance> for further information.
=head1 RETURN VALUES
These functions return a B<EVP_MD> structure that contains the
implementation of the message digest. See L<EVP_MD_meth_new(3)> for
details of the B<EVP_MD> structure.
=head1 CONFORMING TO
ISO/IEC 10118-3:2004.
=head1 SEE ALSO
L<evp(7)>,
L<provider(7)>,
L<EVP_DigestInit(3)>
=head1 COPYRIGHT
-Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/OSSL_CMP_CTX_new.pod b/doc/man3/OSSL_CMP_CTX_new.pod
index 3c4e2d3f7d06..c0c41a226bfe 100644
--- a/doc/man3/OSSL_CMP_CTX_new.pod
+++ b/doc/man3/OSSL_CMP_CTX_new.pod
@@ -1,802 +1,806 @@
=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,
- const 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.
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 re-use.
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)
in RFC 4210's MSG_MAC_ALG for PBM-based message protection.
Default is SHA256.
=item B<OSSL_CMP_OPT_MAC_ALGNID>
The NID of the MAC algorithm to be used in RFC 4210's MSG_MAC_ALG
for PBM-based message protection.
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 messages without CMP-level protection.
+ 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.
=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.
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.
-May be used alternatively to OSSL_CMP_CTX_set0_trustedStore()
-to pin the accepted server.
+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 CMP response messages.
+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 the certificate store of type X509_STORE
-containing trusted (root) CA certificates.
-The store may also hold CRLs and
-a certificate verification callback function used for CMP server authentication.
+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() returns a pointer to the currently set
-certificate store containing trusted cert etc., or an empty store if unset.
+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 CMP client
-certificate, for the TLS client certificate (if any), when verifying
-the CMP server certificate, and when verifying newly enrolled 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 certificate related to the client's private key
-used for CMP message protection.
+OSSL_CMP_CTX_set1_cert() sets the CMP signer certificate
+related to the private key used for CMP 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 augumented set of certs for chain construction.
+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 PBM 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 the byte string I<sec> with length I<len>
as PBM secret in the given I<ctx> or clears it if the I<sec> argument is NULL.
If present, this secret is used to create PBM-based protection of outgoing
messages and to verify any PBM-based protection of incoming messages
(protectionAlg = MSG_MAC_ALG). PBM stands for Password-Based MAC.
PBM-based protection takes precedence over signature-based protection.
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 PBM-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 sucessful 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 client credentials for password-based protection (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-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/doc/man3/OSSL_CMP_MSG_get0_header.pod b/doc/man3/OSSL_CMP_MSG_get0_header.pod
index c3297a3577ac..b3175683c782 100644
--- a/doc/man3/OSSL_CMP_MSG_get0_header.pod
+++ b/doc/man3/OSSL_CMP_MSG_get0_header.pod
@@ -1,147 +1,158 @@
=pod
=head1 NAME
OSSL_CMP_MSG_get0_header,
OSSL_CMP_MSG_get_bodytype,
OSSL_CMP_MSG_update_transactionID,
+OSSL_CMP_MSG_update_recipNonce,
OSSL_CMP_CTX_setup_CRM,
OSSL_CMP_MSG_read,
OSSL_CMP_MSG_write,
d2i_OSSL_CMP_MSG_bio,
i2d_OSSL_CMP_MSG_bio
- function(s) manipulating CMP messages
=head1 SYNOPSIS
#include <openssl/cmp.h>
OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg);
int OSSL_CMP_MSG_get_bodytype(const OSSL_CMP_MSG *msg);
int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+ int OSSL_CMP_MSG_update_recipNonce(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid);
OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file, OSSL_LIB_CTX *libctx, const char *propq);
int OSSL_CMP_MSG_write(const char *file, const OSSL_CMP_MSG *msg);
OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg);
int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg);
=head1 DESCRIPTION
OSSL_CMP_MSG_get0_header() returns the header of the given CMP message.
OSSL_CMP_MSG_get_bodytype() returns the body type of the given CMP message.
OSSL_CMP_MSG_update_transactionID() updates the transactionID field
in the header of the given message according to the CMP_CTX.
-This requires re-protecting the message (if it was protected).
+If I<ctx> does not contain a transaction ID, a fresh one is created before.
+The message gets re-protected (if protecting requests is required).
+
+OSSL_CMP_MSG_update_recipNonce() updates the recipNonce field
+in the header of the given message according to the CMP_CTX.
+The message gets re-protected (if protecting requests is required).
OSSL_CMP_CTX_setup_CRM() creates a CRMF certificate request message
from various information provided in the CMP context argument I<ctx>
for inclusion in a CMP request message based on details contained in I<ctx>.
The I<rid> argument defines the request identifier to use, which typically is 0.
The subject DN included in the certificate template is
the first available value of these:
=over 4
=item any subject name in I<ctx> set via L<OSSL_CMP_CTX_set1_subjectName(3)> -
if it is the NULL-DN (i.e., any empty sequence of RDNs), no subject is included,
=item the subject field of any PKCS#10 CSR set in I<ctx>
via L<OSSL_CMP_CTX_set1_p10CSR(3)>,
=item the subject field of any reference certificate given in I<ctx>
(see L<OSSL_CMP_CTX_set1_oldCert(3)>), but only if I<for_KUR> is nonzero
or the I<ctx> does not include a Subject Alternative Name.
=back
The public key included is the first available value of these:
=over 4
=item the public key derived from any key set via L<OSSL_CMP_CTX_set0_newPkey(3)>,
=item the public key of any PKCS#10 CSR given in I<ctx>,
-=item the public key of any reference certificate given in I<ctx>,
+=item the public key of any reference certificate given in I<ctx>
+(see L<OSSL_CMP_CTX_set1_oldCert(3)>),
=item the public key derived from any client's private key
set via L<OSSL_CMP_CTX_set1_pkey(3)>.
=back
The set of X.509 extensions to include is computed as follows.
If a PKCS#10 CSR is present in I<ctx>, default extensions are taken from there,
otherwise the empty set is taken as the initial value.
If there is a reference certificate in I<ctx> and contains Subject Alternative
Names (SANs) and B<OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT> is not set,
these override any SANs from the PKCS#10 CSR.
The extensions are further augmented or overridden by any extensions with the
same OIDs included in the I<ctx> via L<OSSL_CMP_CTX_set0_reqExtensions(3)>.
The SANs are further overridden by any SANs included in I<ctx> via
L<OSSL_CMP_CTX_push1_subjectAltName(3)>.
Finally, policies are overridden by any policies included in I<ctx> via
L<OSSL_CMP_CTX_push0_policy(3)>.
OSSL_CMP_CTX_setup_CRM() also sets the sets the regToken control B<oldCertID>
for KUR messages using the issuer name and serial number of the reference
certificate, if present.
OSSL_CMP_MSG_read() loads a DER-encoded OSSL_CMP_MSG from I<file>.
OSSL_CMP_MSG_write() stores the given OSSL_CMP_MSG to I<file> in DER encoding.
d2i_OSSL_CMP_MSG_bio() parses an ASN.1-encoded OSSL_CMP_MSG from the BIO I<bio>.
It assigns a pointer to the new structure to I<*msg> if I<msg> is not NULL.
i2d_OSSL_CMP_MSG_bio() writes the OSSL_CMP_MSG I<msg> in ASN.1 encoding
to BIO I<bio>.
=head1 NOTES
CMP is defined in RFC 4210.
=head1 RETURN VALUES
OSSL_CMP_MSG_get0_header() returns the intended pointer value as described above
or NULL if the respective entry does not exist and on error.
OSSL_CMP_MSG_get_bodytype() returns the body type or -1 on error.
OSSL_CMP_CTX_setup_CRM() returns a pointer to a B<OSSL_CRMF_MSG> on success,
NULL on error.
d2i_OSSL_CMP_MSG_bio() returns the parsed message or NULL on error.
OSSL_CMP_MSG_read() and d2i_OSSL_CMP_MSG_bio()
return the parsed CMP message or NULL on error.
OSSL_CMP_MSG_write() returns the number of bytes successfully encoded or a
negative value if an error occurs.
-i2d_OSSL_CMP_MSG_bio() and OSSL_CMP_MSG_update_transactionID() return 1 on
-success, 0 on error.
+i2d_OSSL_CMP_MSG_bio(), OSSL_CMP_MSG_update_transactionID(),
+and OSSL_CMP_MSG_update_recipNonce()
+return 1 on success, 0 on error.
=head1 SEE ALSO
L<OSSL_CMP_CTX_set1_subjectName(3)>, L<OSSL_CMP_CTX_set1_p10CSR(3)>,
L<OSSL_CMP_CTX_set1_oldCert(3)>, L<OSSL_CMP_CTX_set0_newPkey(3)>,
L<OSSL_CMP_CTX_set1_pkey(3)>, L<OSSL_CMP_CTX_set0_reqExtensions(3)>,
L<OSSL_CMP_CTX_push1_subjectAltName(3)>, L<OSSL_CMP_CTX_push0_policy(3)>
=head1 HISTORY
The OpenSSL CMP support was added in OpenSSL 3.0.
+OSSL_CMP_MSG_update_recipNonce() was added in OpenSSL 3.0.9.
+
=head1 COPYRIGHT
-Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man3/OSSL_CRMF_MSG_set0_validity.pod b/doc/man3/OSSL_CRMF_MSG_set0_validity.pod
index a87b7d530715..93185a5528d8 100644
--- a/doc/man3/OSSL_CRMF_MSG_set0_validity.pod
+++ b/doc/man3/OSSL_CRMF_MSG_set0_validity.pod
@@ -1,120 +1,120 @@
=pod
=head1 NAME
OSSL_CRMF_MSG_set0_validity,
OSSL_CRMF_MSG_set_certReqId,
OSSL_CRMF_CERTTEMPLATE_fill,
OSSL_CRMF_MSG_set0_extensions,
OSSL_CRMF_MSG_push0_extension,
OSSL_CRMF_MSG_create_popo,
OSSL_CRMF_MSGS_verify_popo
- functions populating and verifying CRMF CertReqMsg structures
=head1 SYNOPSIS
#include <openssl/crmf.h>
int OSSL_CRMF_MSG_set0_validity(OSSL_CRMF_MSG *crm,
ASN1_TIME *notBefore, ASN1_TIME *notAfter);
int OSSL_CRMF_MSG_set_certReqId(OSSL_CRMF_MSG *crm, int rid);
int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
EVP_PKEY *pubkey,
const X509_NAME *subject,
const X509_NAME *issuer,
const ASN1_INTEGER *serial);
int OSSL_CRMF_MSG_set0_extensions(OSSL_CRMF_MSG *crm, X509_EXTENSIONS *exts);
int OSSL_CRMF_MSG_push0_extension(OSSL_CRMF_MSG *crm, X509_EXTENSION *ext);
int OSSL_CRMF_MSG_create_popo(int meth, OSSL_CRMF_MSG *crm,
EVP_PKEY *pkey, const EVP_MD *digest,
OSSL_LIB_CTX *libctx, const char *propq);
int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
int rid, int acceptRAVerified,
OSSL_LIB_CTX *libctx, const char *propq);
=head1 DESCRIPTION
OSSL_CRMF_MSG_set0_validity() sets the I<notBefore> and I<notAfter> fields
as validity constraints in the certTemplate of I<crm>.
Any of the I<notBefore> and I<notAfter> parameters may be NULL,
which means no constraint for the respective field.
On success ownership of I<notBefore> and I<notAfter> is transferred to I<crm>.
OSSL_CRMF_MSG_set_certReqId() sets I<rid> as the certReqId of I<crm>.
OSSL_CRMF_CERTTEMPLATE_fill() sets those fields of the certTemplate I<tmpl>
for which non-NULL values are provided: I<pubkey>, I<subject>, I<issuer>,
and/or I<serial>.
X.509 extensions may be set using OSSL_CRMF_MSG_set0_extensions().
On success the reference counter of the I<pubkey> (if given) is incremented,
while the I<subject>, I<issuer>, and I<serial> structures (if given) are copied.
OSSL_CRMF_MSG_set0_extensions() sets I<exts> as the extensions in the
certTemplate of I<crm>. Frees any pre-existing ones and consumes I<exts>.
OSSL_CRMF_MSG_push0_extension() pushes the X509 extension I<ext> to the
extensions in the certTemplate of I<crm>. Consumes I<ext>.
OSSL_CRMF_MSG_create_popo() creates and sets the Proof-of-Possession (POPO)
according to the method I<meth> in I<crm>.
The library context I<libctx> and property query string I<propq>,
may be NULL to select the defaults.
In case the method is OSSL_CRMF_POPO_SIGNATURE the POPO is calculated
using the private key I<pkey> and the digest method I<digest>,
where the I<digest> argument is ignored if I<pkey> is of a type (such as
-Ed25519 and Ed448) that is implicitly associated with a digest alorithm.
+Ed25519 and Ed448) that is implicitly associated with a digest algorithm.
I<meth> can be one of the following:
=over 8
=item * OSSL_CRMF_POPO_NONE - RFC 4211, section 4, POP field omitted.
CA/RA uses out-of-band method to verify POP. Note that servers may fail in this
case, resulting for instance in HTTP error code 500 (Internal error).
=item * OSSL_CRMF_POPO_RAVERIFIED - RFC 4211, section 4, explicit indication
that the RA has already verified the POP.
=item * OSSL_CRMF_POPO_SIGNATURE - RFC 4211, section 4.1, only case 3 supported
so far.
=item * OSSL_CRMF_POPO_KEYENC - RFC 4211, section 4.2, only indirect method
(subsequentMessage/enccert) supported,
challenge-response exchange (challengeResp) not yet supported.
=item * OSSL_CRMF_POPO_KEYAGREE - RFC 4211, section 4.3, not yet supported.
=back
OSSL_CRMF_MSGS_verify_popo verifies the Proof-of-Possession of the request with
the given I<rid> in the list of I<reqs>. Optionally accepts RAVerified. It can
make use of the library context I<libctx> and property query string I<propq>.
=head1 RETURN VALUES
All functions return 1 on success, 0 on error.
=head1 SEE ALSO
RFC 4211
=head1 HISTORY
The OpenSSL CRMF support was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man3/OSSL_DECODER_from_bio.pod b/doc/man3/OSSL_DECODER_from_bio.pod
index 5118dee9ac8b..0cefeb2bf545 100644
--- a/doc/man3/OSSL_DECODER_from_bio.pod
+++ b/doc/man3/OSSL_DECODER_from_bio.pod
@@ -1,120 +1,120 @@
=pod
=head1 NAME
OSSL_DECODER_from_data,
OSSL_DECODER_from_bio,
OSSL_DECODER_from_fp
- Routines to perform a decoding
=head1 SYNOPSIS
#include <openssl/decoder.h>
int OSSL_DECODER_from_bio(OSSL_DECODER_CTX *ctx, BIO *in);
int OSSL_DECODER_from_fp(OSSL_DECODER_CTX *ctx, FILE *fp);
int OSSL_DECODER_from_data(OSSL_DECODER_CTX *ctx, const unsigned char **pdata,
size_t *pdata_len);
Feature availability macros:
=over 4
=item OSSL_DECODER_from_fp() is only available when B<OPENSSL_NO_STDIO>
is undefined.
=back
=head1 DESCRIPTION
OSSL_DECODER_from_data() runs the decoding process for the context I<ctx>,
with input coming from I<*pdata>, I<*pdata_len> bytes long. Both I<*pdata>
and I<*pdata_len> must be non-NULL. When OSSL_DECODER_from_data() returns,
I<*pdata> is updated to point at the location after what has been decoded,
and I<*pdata_len> to have the number of remaining bytes.
OSSL_DECODER_from_bio() runs the decoding process for the context I<ctx>,
with the input coming from the B<BIO> I<in>. Should it make a difference,
it's recommended to have the BIO set in binary mode rather than text mode.
OSSL_DECODER_from_fp() does the same thing as OSSL_DECODER_from_bio(),
except that the input is coming from the B<FILE> I<fp>.
=head1 RETURN VALUES
-OSSL_DECODER_from_bio() and OSSL_DECODER_from_fp() return 1 on success, or 0
-on failure.
+OSSL_DECODER_from_bio(), OSSL_DECODER_from_data() and OSSL_DECODER_from_fp()
+return 1 on success, or 0 on failure.
=head1 EXAMPLES
To decode an RSA key encoded with PEM from a bio:
OSSL_DECODER_CTX *dctx;
EVP_PKEY *pkey = NULL;
const char *format = "PEM"; /* NULL for any format */
const char *structure = NULL; /* any structure */
const char *keytype = "RSA"; /* NULL for any key */
const unsigned char *pass = "my password";
dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, format, structure,
keytype,
OSSL_KEYMGMT_SELECT_KEYPAIR,
NULL, NULL);
if (dctx == NULL) {
/* error: no suitable potential decoders found */
}
if (pass != NULL)
OSSL_DECODER_CTX_set_passphrase(dctx, pass, strlen(pass));
if (OSSL_DECODER_from_bio(dctx, bio)) {
/* pkey is created with the decoded data from the bio */
} else {
/* decoding failure */
}
OSSL_DECODER_CTX_free(dctx);
To decode an EC key encoded with DER from a buffer:
OSSL_DECODER_CTX *dctx;
EVP_PKEY *pkey = NULL;
const char *format = "DER"; /* NULL for any format */
const char *structure = NULL; /* any structure */
const char *keytype = "EC"; /* NULL for any key */
const unsigned char *pass = NULL
const unsigned char *data = buffer;
size_t datalen = sizeof(buffer);
dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, format, structure,
keytype,
OSSL_KEYMGMT_SELECT_KEYPAIR
| OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
NULL, NULL);
if (dctx == NULL) {
/* error: no suitable potential decoders found */
}
if (pass != NULL)
OSSL_DECODER_CTX_set_passphrase(dctx, pass, strlen(pass));
if (OSSL_DECODER_from_data(dctx, &data, &datalen)) {
/* pkey is created with the decoded data from the buffer */
} else {
/* decoding failure */
}
OSSL_DECODER_CTX_free(dctx);
=head1 SEE ALSO
L<provider(7)>, L<OSSL_DECODER_CTX(3)>
=head1 HISTORY
The functions described here were added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man3/OSSL_PARAM.pod b/doc/man3/OSSL_PARAM.pod
index 0aad61924f79..3939ddc74296 100644
--- a/doc/man3/OSSL_PARAM.pod
+++ b/doc/man3/OSSL_PARAM.pod
@@ -1,366 +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 */
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<requestor>) sets up the B<OSSL_PARAM> array and
+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<requestor> and pointed at with the B<OSSL_PARAM> I<data>.
+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 accomodate 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<requestor> to figure out dynamically exactly
+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-2022 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man3/OSSL_PARAM_int.pod b/doc/man3/OSSL_PARAM_int.pod
index 8864404a7a15..c03e30f83965 100644
--- a/doc/man3/OSSL_PARAM_int.pod
+++ b/doc/man3/OSSL_PARAM_int.pod
@@ -1,413 +1,413 @@
=pod
=head1 NAME
OSSL_PARAM_double, OSSL_PARAM_int, OSSL_PARAM_int32, OSSL_PARAM_int64,
OSSL_PARAM_long, OSSL_PARAM_size_t, OSSL_PARAM_time_t, OSSL_PARAM_uint,
OSSL_PARAM_uint32, OSSL_PARAM_uint64, OSSL_PARAM_ulong, OSSL_PARAM_BN,
OSSL_PARAM_utf8_string, OSSL_PARAM_octet_string, OSSL_PARAM_utf8_ptr,
OSSL_PARAM_octet_ptr,
OSSL_PARAM_END, OSSL_PARAM_DEFN,
OSSL_PARAM_construct_double, OSSL_PARAM_construct_int,
OSSL_PARAM_construct_int32, OSSL_PARAM_construct_int64,
OSSL_PARAM_construct_long, OSSL_PARAM_construct_size_t,
OSSL_PARAM_construct_time_t, OSSL_PARAM_construct_uint,
OSSL_PARAM_construct_uint32, OSSL_PARAM_construct_uint64,
OSSL_PARAM_construct_ulong, OSSL_PARAM_construct_BN,
OSSL_PARAM_construct_utf8_string, OSSL_PARAM_construct_utf8_ptr,
OSSL_PARAM_construct_octet_string, OSSL_PARAM_construct_octet_ptr,
OSSL_PARAM_construct_end,
OSSL_PARAM_locate, OSSL_PARAM_locate_const,
OSSL_PARAM_get_double, OSSL_PARAM_get_int, OSSL_PARAM_get_int32,
OSSL_PARAM_get_int64, OSSL_PARAM_get_long, OSSL_PARAM_get_size_t,
OSSL_PARAM_get_time_t, OSSL_PARAM_get_uint, OSSL_PARAM_get_uint32,
OSSL_PARAM_get_uint64, OSSL_PARAM_get_ulong, OSSL_PARAM_get_BN,
OSSL_PARAM_get_utf8_string, OSSL_PARAM_get_octet_string,
OSSL_PARAM_get_utf8_ptr, OSSL_PARAM_get_octet_ptr,
OSSL_PARAM_get_utf8_string_ptr, OSSL_PARAM_get_octet_string_ptr,
OSSL_PARAM_set_double, OSSL_PARAM_set_int, OSSL_PARAM_set_int32,
OSSL_PARAM_set_int64, OSSL_PARAM_set_long, OSSL_PARAM_set_size_t,
OSSL_PARAM_set_time_t, OSSL_PARAM_set_uint, OSSL_PARAM_set_uint32,
OSSL_PARAM_set_uint64, OSSL_PARAM_set_ulong, OSSL_PARAM_set_BN,
OSSL_PARAM_set_utf8_string, OSSL_PARAM_set_octet_string,
OSSL_PARAM_set_utf8_ptr, OSSL_PARAM_set_octet_ptr,
OSSL_PARAM_UNMODIFIED, OSSL_PARAM_modified, OSSL_PARAM_set_all_unmodified
- OSSL_PARAM helpers
=head1 SYNOPSIS
=for openssl generic
#include <openssl/params.h>
/*
* TYPE in function names is one of:
* double, int, int32, int64, long, size_t, time_t, uint, uint32, uint64, ulong
* Corresponding TYPE in function arguments is one of:
* double, int, int32_t, int64_t, long, size_t, time_t, unsigned int, uint32_t,
* uint64_t, unsigned long
*/
#define OSSL_PARAM_TYPE(key, address)
#define OSSL_PARAM_BN(key, address, size)
#define OSSL_PARAM_utf8_string(key, address, size)
#define OSSL_PARAM_octet_string(key, address, size)
#define OSSL_PARAM_utf8_ptr(key, address, size)
#define OSSL_PARAM_octet_ptr(key, address, size)
#define OSSL_PARAM_END
#define OSSL_PARAM_UNMODIFIED
#define OSSL_PARAM_DEFN(key, type, addr, sz) \
{ (key), (type), (addr), (sz), OSSL_PARAM_UNMODIFIED }
OSSL_PARAM OSSL_PARAM_construct_TYPE(const char *key, TYPE *buf);
OSSL_PARAM OSSL_PARAM_construct_BN(const char *key, unsigned char *buf,
size_t bsize);
OSSL_PARAM OSSL_PARAM_construct_utf8_string(const char *key, char *buf,
size_t bsize);
OSSL_PARAM OSSL_PARAM_construct_octet_string(const char *key, void *buf,
size_t bsize);
OSSL_PARAM OSSL_PARAM_construct_utf8_ptr(const char *key, char **buf,
size_t bsize);
OSSL_PARAM OSSL_PARAM_construct_octet_ptr(const char *key, void **buf,
size_t bsize);
OSSL_PARAM OSSL_PARAM_construct_end(void);
OSSL_PARAM *OSSL_PARAM_locate(OSSL_PARAM *array, const char *key);
const OSSL_PARAM *OSSL_PARAM_locate_const(const OSSL_PARAM *array,
const char *key);
int OSSL_PARAM_get_TYPE(const OSSL_PARAM *p, TYPE *val);
int OSSL_PARAM_set_TYPE(OSSL_PARAM *p, TYPE val);
int OSSL_PARAM_get_BN(const OSSL_PARAM *p, BIGNUM **val);
int OSSL_PARAM_set_BN(OSSL_PARAM *p, const BIGNUM *val);
int OSSL_PARAM_get_utf8_string(const OSSL_PARAM *p, char **val,
size_t max_len);
int OSSL_PARAM_set_utf8_string(OSSL_PARAM *p, const char *val);
int OSSL_PARAM_get_octet_string(const OSSL_PARAM *p, void **val,
size_t max_len, size_t *used_len);
int OSSL_PARAM_set_octet_string(OSSL_PARAM *p, const void *val, size_t len);
int OSSL_PARAM_get_utf8_ptr(const OSSL_PARAM *p, const char **val);
int OSSL_PARAM_set_utf8_ptr(OSSL_PARAM *p, const char *val);
int OSSL_PARAM_get_octet_ptr(const OSSL_PARAM *p, const void **val,
size_t *used_len);
int OSSL_PARAM_set_octet_ptr(OSSL_PARAM *p, const void *val,
size_t used_len);
int OSSL_PARAM_get_utf8_string_ptr(const OSSL_PARAM *p, const char **val);
int OSSL_PARAM_get_octet_string_ptr(const OSSL_PARAM *p, const void **val,
size_t *used_len);
int OSSL_PARAM_modified(const OSSL_PARAM *param);
void OSSL_PARAM_set_all_unmodified(OSSL_PARAM *params);
=head1 DESCRIPTION
A collection of utility functions that simplify and add type safety to the
L<OSSL_PARAM(3)> arrays. The following B<I<TYPE>> names are supported:
=over 1
=item *
double
=item *
int
=item *
int32 (int32_t)
=item *
int64 (int64_t)
=item *
long int (long)
=item *
time_t
=item *
size_t
=item *
uint32 (uint32_t)
=item *
uint64 (uint64_t)
=item *
unsigned int (uint)
=item *
unsigned long int (ulong)
=back
OSSL_PARAM_TYPE() are a series of macros designed to assist initialising an
array of L<OSSL_PARAM(3)> structures.
Each of these macros defines a parameter of the specified B<I<TYPE>> with the
provided I<key> and parameter variable I<address>.
OSSL_PARAM_utf8_string(), OSSL_PARAM_octet_string(), OSSL_PARAM_utf8_ptr(),
OSSL_PARAM_octet_ptr(), OSSL_PARAM_BN() are macros that provide support
for defining UTF8 strings, OCTET strings and big numbers.
A parameter with name I<key> is defined.
The storage for this parameter is at I<address> and is of I<size> bytes.
OSSL_PARAM_END provides an end of parameter list marker.
This should terminate all L<OSSL_PARAM(3)> arrays.
The OSSL_PARAM_DEFN() macro provides the ability to construct a single
L<OSSL_PARAM(3)> (typically used in the construction of B<OSSL_PARAM> arrays). The
I<key>, I<type>, I<addr> and I<sz> arguments correspond to the I<key>,
I<data_type>, I<data> and I<data_size> fields of the L<OSSL_PARAM(3)> structure as
described on the L<OSSL_PARAM(3)> page.
OSSL_PARAM_construct_TYPE() are a series of functions that create L<OSSL_PARAM(3)>
records dynamically.
A parameter with name I<key> is created.
The parameter will use storage pointed to by I<buf> and return size of I<ret>.
OSSL_PARAM_construct_BN() is a function that constructs a large integer
L<OSSL_PARAM(3)> structure.
A parameter with name I<key>, storage I<buf>, size I<bsize> and return
size I<rsize> is created.
OSSL_PARAM_construct_utf8_string() is a function that constructs a UTF8
string L<OSSL_PARAM(3)> structure.
A parameter with name I<key>, storage I<buf> and size I<bsize> is created.
If I<bsize> is zero, the string length is determined using strlen(3).
Generally pass zero for I<bsize> instead of calling strlen(3) yourself.
OSSL_PARAM_construct_octet_string() is a function that constructs an OCTET
string L<OSSL_PARAM(3)> structure.
A parameter with name I<key>, storage I<buf> and size I<bsize> is created.
OSSL_PARAM_construct_utf8_ptr() is a function that constructs a UTF8 string
pointer L<OSSL_PARAM(3)> structure.
A parameter with name I<key>, storage pointer I<*buf> and size I<bsize>
is created.
OSSL_PARAM_construct_octet_ptr() is a function that constructs an OCTET string
pointer L<OSSL_PARAM(3)> structure.
A parameter with name I<key>, storage pointer I<*buf> and size I<bsize>
is created.
OSSL_PARAM_construct_end() is a function that constructs the terminating
L<OSSL_PARAM(3)> structure.
OSSL_PARAM_locate() is a function that searches an I<array> of parameters for
the one matching the I<key> name.
OSSL_PARAM_locate_const() behaves exactly like OSSL_PARAM_locate() except for
the presence of I<const> for the I<array> argument and its return value.
OSSL_PARAM_get_TYPE() retrieves a value of type B<I<TYPE>> from the parameter
I<p>.
The value is copied to the address I<val>.
Type coercion takes place as discussed in the NOTES section.
OSSL_PARAM_set_TYPE() stores a value I<val> of type B<I<TYPE>> into the
parameter I<p>.
If the parameter's I<data> field is NULL, then only its I<return_size> field
will be assigned the size the parameter's I<data> buffer should have.
Type coercion takes place as discussed in the NOTES section.
OSSL_PARAM_get_BN() retrieves a BIGNUM from the parameter pointed to by I<p>.
The BIGNUM referenced by I<val> is updated and is allocated if I<*val> is
NULL.
OSSL_PARAM_set_BN() stores the BIGNUM I<val> into the parameter I<p>.
If the parameter's I<data> field is NULL, then only its I<return_size> field
will be assigned the size the parameter's I<data> buffer should have.
OSSL_PARAM_get_utf8_string() retrieves a UTF8 string from the parameter
pointed to by I<p>.
The string is stored into I<*val> with a size limit of I<max_len>,
which must be large enough to accomodate a terminating NUL byte,
otherwise this function will fail.
If I<*val> is NULL, memory is allocated for the string (including the
terminating NUL byte) and I<max_len> is ignored.
If memory is allocated by this function, it must be freed by the caller.
OSSL_PARAM_set_utf8_string() sets a UTF8 string from the parameter pointed to
by I<p> to the value referenced by I<val>.
If the parameter's I<data> field isn't NULL, its I<data_size> must indicate
that the buffer is large enough to accomodate the string that I<val> points at,
not including the terminating NUL byte, or this function will fail.
A terminating NUL byte is added only if the parameter's I<data_size> indicates
the buffer is longer than the string length, otherwise the string will not be
NUL terminated.
If the parameter's I<data> field is NULL, then only its I<return_size> field
will be assigned the minimum size the parameter's I<data> buffer should have
to accomodate the string, not including a terminating NUL byte.
OSSL_PARAM_get_octet_string() retrieves an OCTET string from the parameter
pointed to by I<p>.
The OCTETs are either stored into I<*val> with a length limit of I<max_len> or,
in the case when I<*val> is NULL, memory is allocated and
I<max_len> is ignored. I<*used_len> is populated with the number of OCTETs
stored. If I<val> is NULL then the OCTETS are not stored, but I<*used_len> is
still populated.
If memory is allocated by this function, it must be freed by the caller.
OSSL_PARAM_set_octet_string() sets an OCTET string from the parameter
pointed to by I<p> to the value referenced by I<val>.
If the parameter's I<data> field is NULL, then only its I<return_size> field
will be assigned the size the parameter's I<data> buffer should have.
OSSL_PARAM_get_utf8_ptr() retrieves the UTF8 string pointer from the parameter
referenced by I<p> and stores it in I<*val>.
OSSL_PARAM_set_utf8_ptr() sets the UTF8 string pointer in the parameter
referenced by I<p> to the values I<val>.
OSSL_PARAM_get_octet_ptr() retrieves the OCTET string pointer from the parameter
referenced by I<p> and stores it in I<*val>.
The length of the OCTET string is stored in I<*used_len>.
OSSL_PARAM_set_octet_ptr() sets the OCTET string pointer in the parameter
referenced by I<p> to the values I<val>.
The length of the OCTET string is provided by I<used_len>.
OSSL_PARAM_get_utf8_string_ptr() retrieves the pointer to a UTF8 string from
the parameter pointed to by I<p>, and stores that pointer in I<*val>.
This is different from OSSL_PARAM_get_utf8_string(), which copies the
string.
OSSL_PARAM_get_octet_string_ptr() retrieves the pointer to a octet string
from the parameter pointed to by I<p>, and stores that pointer in I<*val>,
along with the string's length in I<*used_len>.
This is different from OSSL_PARAM_get_octet_string(), which copies the
string.
The OSSL_PARAM_UNMODIFIED macro is used to detect if a parameter was set. On
creation, via either the macros or construct calls, the I<return_size> field
is set to this. If the parameter is set using the calls defined herein, the
I<return_size> field is changed.
OSSL_PARAM_modified() queries if the parameter I<param> has been set or not
using the calls defined herein.
OSSL_PARAM_set_all_unmodified() resets the unused indicator for all parameters
in the array I<params>.
=head1 RETURN VALUES
OSSL_PARAM_construct_TYPE(), OSSL_PARAM_construct_BN(),
OSSL_PARAM_construct_utf8_string(), OSSL_PARAM_construct_octet_string(),
OSSL_PARAM_construct_utf8_ptr() and OSSL_PARAM_construct_octet_ptr()
return a populated L<OSSL_PARAM(3)> structure.
OSSL_PARAM_locate() and OSSL_PARAM_locate_const() return a pointer to
the matching L<OSSL_PARAM(3)> object. They return NULL on error or when
no object matching I<key> exists in the I<array>.
OSSL_PARAM_modified() returns 1 if the parameter was set and 0 otherwise.
All other functions return 1 on success and 0 on failure.
=head1 NOTES
Native types will be converted as required only if the value is exactly
representable by the target type or parameter.
Apart from that, the functions must be used appropriately for the
expected type of the parameter.
OSSL_PARAM_get_BN() and OSSL_PARAM_set_BN() currently only support
nonnegative B<BIGNUM>s, and by consequence, only
B<OSSL_PARAM_UNSIGNED_INTEGER>. OSSL_PARAM_construct_BN() currently
constructs an L<OSSL_PARAM(3)> structure with the data type
B<OSSL_PARAM_UNSIGNED_INTEGER>.
For OSSL_PARAM_construct_utf8_ptr() and OSSL_PARAM_consstruct_octet_ptr(),
I<bsize> is not relevant if the purpose is to send the L<OSSL_PARAM(3)> array
to a I<responder>, i.e. to get parameter data back.
In that case, I<bsize> can safely be given zero.
See L<OSSL_PARAM(3)/DESCRIPTION> for further information on the
possible purposes.
=head1 EXAMPLES
Reusing the examples from L<OSSL_PARAM(3)> to just show how
L<OSSL_PARAM(3)> arrays can be handled using the macros and functions
defined herein.
=head2 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";
const OSSL_PARAM set[] = {
OSSL_PARAM_utf8_ptr("foo", &foo, foo_l),
OSSL_PARAM_utf8_string("bar", bar, sizeof(bar) - 1),
OSSL_PARAM_END
};
=head2 Example 2
This example is for requesting parameters on some object, and also
-demonstrates that the requestor isn't obligated to request all
+demonstrates that the requester isn't obligated to request all
available parameters:
const char *foo = NULL;
char bar[1024];
OSSL_PARAM request[] = {
OSSL_PARAM_utf8_ptr("foo", &foo, 0),
OSSL_PARAM_utf8_string("bar", bar, sizeof(bar)),
OSSL_PARAM_END
};
A I<responder> that receives this array (as C<params> in this example)
could fill in the parameters like this:
/* OSSL_PARAM *params */
OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate(params, "foo")) != NULL)
OSSL_PARAM_set_utf8_ptr(p, "foo value");
if ((p = OSSL_PARAM_locate(params, "bar")) != NULL)
OSSL_PARAM_set_utf8_string(p, "bar value");
if ((p = OSSL_PARAM_locate(params, "cookie")) != NULL)
OSSL_PARAM_set_utf8_ptr(p, "cookie value");
=head1 SEE ALSO
L<openssl-core.h(7)>, L<OSSL_PARAM(3)>
=head1 HISTORY
These APIs were introduced in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man3/PEM_read_CMS.pod b/doc/man3/PEM_read_CMS.pod
index 2b96db9c31a3..dbccf26cd893 100644
--- a/doc/man3/PEM_read_CMS.pod
+++ b/doc/man3/PEM_read_CMS.pod
@@ -1,153 +1,152 @@
=pod
=head1 NAME
DECLARE_PEM_rw,
PEM_read_CMS,
PEM_read_bio_CMS,
PEM_write_CMS,
PEM_write_bio_CMS,
PEM_write_DHxparams,
PEM_write_bio_DHxparams,
PEM_read_ECPKParameters,
PEM_read_bio_ECPKParameters,
PEM_write_ECPKParameters,
PEM_write_bio_ECPKParameters,
PEM_read_ECPrivateKey,
PEM_write_ECPrivateKey,
PEM_write_bio_ECPrivateKey,
PEM_read_EC_PUBKEY,
PEM_read_bio_EC_PUBKEY,
PEM_write_EC_PUBKEY,
PEM_write_bio_EC_PUBKEY,
PEM_read_NETSCAPE_CERT_SEQUENCE,
PEM_read_bio_NETSCAPE_CERT_SEQUENCE,
PEM_write_NETSCAPE_CERT_SEQUENCE,
PEM_write_bio_NETSCAPE_CERT_SEQUENCE,
PEM_read_PKCS8,
PEM_read_bio_PKCS8,
PEM_write_PKCS8,
PEM_write_bio_PKCS8,
PEM_write_PKCS8_PRIV_KEY_INFO,
PEM_read_bio_PKCS8_PRIV_KEY_INFO,
PEM_read_PKCS8_PRIV_KEY_INFO,
PEM_write_bio_PKCS8_PRIV_KEY_INFO,
PEM_read_SSL_SESSION,
PEM_read_bio_SSL_SESSION,
PEM_write_SSL_SESSION,
PEM_write_bio_SSL_SESSION,
PEM_read_X509_PUBKEY,
PEM_read_bio_X509_PUBKEY,
PEM_write_X509_PUBKEY,
PEM_write_bio_X509_PUBKEY
- PEM object encoding routines
=head1 SYNOPSIS
=for openssl generic
#include <openssl/pem.h>
DECLARE_PEM_rw(name, TYPE)
TYPE *PEM_read_TYPE(FILE *fp, TYPE **a, pem_password_cb *cb, void *u);
TYPE *PEM_read_bio_TYPE(BIO *bp, TYPE **a, pem_password_cb *cb, void *u);
int PEM_write_TYPE(FILE *fp, const TYPE *a);
int PEM_write_bio_TYPE(BIO *bp, const TYPE *a);
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)>:
#include <openssl/pem.h>
int PEM_write_DHxparams(FILE *out, const DH *dh);
int PEM_write_bio_DHxparams(BIO *out, const DH *dh);
EC_GROUP *PEM_read_ECPKParameters(FILE *fp, EC_GROUP **x, pem_password_cb *cb, void *u);
EC_GROUP *PEM_read_bio_ECPKParameters(BIO *bp, EC_GROUP **x, pem_password_cb *cb, void *u);
int PEM_write_ECPKParameters(FILE *out, const EC_GROUP *x);
int PEM_write_bio_ECPKParameters(BIO *out, const EC_GROUP *x),
EC_KEY *PEM_read_EC_PUBKEY(FILE *fp, EC_KEY **x, pem_password_cb *cb, void *u);
EC_KEY *PEM_read_bio_EC_PUBKEY(BIO *bp, EC_KEY **x, pem_password_cb *cb, void *u);
int PEM_write_EC_PUBKEY(FILE *out, const EC_KEY *x);
int PEM_write_bio_EC_PUBKEY(BIO *out, const EC_KEY *x);
EC_KEY *PEM_read_ECPrivateKey(FILE *out, EC_KEY **x, pem_password_cb *cb, void *u);
EC_KEY *PEM_read_bio_ECPrivateKey(BIO *out, EC_KEY **x, pem_password_cb *cb, void *u);
int PEM_write_ECPrivateKey(FILE *out, const EC_KEY *x, const EVP_CIPHER *enc,
const unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_bio_ECPrivateKey(BIO *out, const EC_KEY *x, const EVP_CIPHER *enc,
const unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
=head1 DESCRIPTION
All of the functions described on this page are deprecated.
Applications should use OSSL_ENCODER_to_bio() and OSSL_DECODER_from_bio()
instead.
In the description below, B<I<TYPE>> is used
as a placeholder for any of the OpenSSL datatypes, such as B<X509>.
The macro B<DECLARE_PEM_rw> expands to the set of declarations shown in
the next four lines of the synopsis.
These routines convert between local instances of ASN1 datatypes and
the PEM encoding. For more information on the templates, see
L<ASN1_ITEM(3)>. For more information on the lower-level routines used
by the functions here, see L<PEM_read(3)>.
B<PEM_read_I<TYPE>>() reads a PEM-encoded object of B<I<TYPE>> from the file
I<fp> and returns it. The I<cb> and I<u> parameters are as described in
L<pem_password_cb(3)>.
B<PEM_read_bio_I<TYPE>>() is similar to B<PEM_read_I<TYPE>>() but reads from
the BIO I<bp>.
B<PEM_write_I<TYPE>>() writes the PEM encoding of the object I<a> to the file
I<fp>.
B<PEM_write_bio_I<TYPE>>() similarly writes to the BIO I<bp>.
=head1 NOTES
These functions make no assumption regarding the pass phrase received from the
password callback.
It will simply be treated as a byte sequence.
=head1 RETURN VALUES
B<PEM_read_I<TYPE>>() and B<PEM_read_bio_I<TYPE>>() return a pointer to an
allocated object, which should be released by calling B<I<TYPE>_free>(), or
NULL on error.
-B<PEM_write_I<TYPE>>() and B<PEM_write_bio_I<TYPE>>() return the number of bytes
-written or zero on error.
+B<PEM_write_I<TYPE>>() and B<PEM_write_bio_I<TYPE>>() return 1 for success or 0 for failure.
=head1 SEE ALSO
L<PEM_read(3)>,
L<passphrase-encoding(7)>
=head1 HISTORY
The functions PEM_write_DHxparams(), PEM_write_bio_DHxparams(),
PEM_read_ECPKParameters(), PEM_read_bio_ECPKParameters(),
PEM_write_ECPKParameters(), PEM_write_bio_ECPKParameters(),
PEM_read_EC_PUBKEY(), PEM_read_bio_EC_PUBKEY(),
PEM_write_EC_PUBKEY(), PEM_write_bio_EC_PUBKEY(),
PEM_read_ECPrivateKey(), PEM_read_bio_ECPrivateKey(),
PEM_write_ECPrivateKey() and PEM_write_bio_ECPrivateKey()
were deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 1998-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/doc/man3/PKCS7_sign.pod b/doc/man3/PKCS7_sign.pod
index c0a07090759b..1d997045fe14 100644
--- a/doc/man3/PKCS7_sign.pod
+++ b/doc/man3/PKCS7_sign.pod
@@ -1,132 +1,132 @@
=pod
=head1 NAME
PKCS7_sign_ex, PKCS7_sign
- create a PKCS#7 signedData structure
=head1 SYNOPSIS
#include <openssl/pkcs7.h>
PKCS7 *PKCS7_sign_ex(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
BIO *data, int flags, OSSL_LIB_CTX *libctx,
const char *propq);
PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
BIO *data, int flags);
=head1 DESCRIPTION
PKCS7_sign_ex() creates and returns a PKCS#7 signedData structure.
I<signcert> is the certificate to sign with, I<pkey> is the corresponding
private key. I<certs> is an optional set of extra certificates to include
in the PKCS#7 structure (for example any intermediate CAs in the chain).
The library context I<libctx> and property query I<propq> are used when
retrieving algorithms from providers.
The data to be signed is read from BIO I<data>.
I<flags> is an optional set of flags.
Any of the following flags (ored together) can be passed in the I<flags>
parameter.
Many S/MIME clients expect the signed content to include valid MIME headers. If
the B<PKCS7_TEXT> flag is set MIME headers for type C<text/plain> are prepended
to the data.
If B<PKCS7_NOCERTS> is set the signer's certificate and the extra I<certs>
will not be included in the PKCS7 structure.
The signer's certificate must still be supplied in the I<signcert> parameter
though. This can reduce the size of the signatures if the signer's certificates
can be obtained by other means: for example a previously signed message.
The data being signed is included in the PKCS7 structure, unless
B<PKCS7_DETACHED> is set in which case it is omitted. This is used for PKCS7
detached signatures which are used in S/MIME plaintext signed messages for
example.
Normally the supplied content is translated into MIME canonical format (as
required by the S/MIME specifications) if B<PKCS7_BINARY> is set no translation
occurs. This option should be used if the supplied data is in binary format
otherwise the translation will corrupt it.
The signedData structure includes several PKCS#7 authenticatedAttributes
including the signing time, the PKCS#7 content type and the supported list of
ciphers in an SMIMECapabilities attribute. If B<PKCS7_NOATTR> is set then no
authenticatedAttributes will be used. If B<PKCS7_NOSMIMECAP> is set then just
the SMIMECapabilities are omitted.
If present the SMIMECapabilities attribute indicates support for the following
algorithms: triple DES, 128 bit RC2, 64 bit RC2, DES and 40 bit RC2. If any of
these algorithms is disabled then it will not be included.
If the flags B<PKCS7_STREAM> is set then the returned B<PKCS7> structure is
just initialized ready to perform the signing operation. The signing is however
B<not> performed and the data to be signed is not read from the I<data>
parameter. Signing is deferred until after the data has been written. In this
way data can be signed in a single pass.
If the B<PKCS7_PARTIAL> flag is set a partial B<PKCS7> structure is output to
which additional signers and capabilities can be added before finalization.
If the flag B<PKCS7_STREAM> is set the returned B<PKCS7> structure is B<not>
complete and outputting its contents via a function that does not properly
finalize the B<PKCS7> structure will give unpredictable results.
Several functions including SMIME_write_PKCS7(), i2d_PKCS7_bio_stream(),
PEM_write_bio_PKCS7_stream() finalize the structure. Alternatively finalization
can be performed by obtaining the streaming ASN1 B<BIO> directly using
BIO_new_PKCS7().
If a signer is specified it will use the default digest for the signing
algorithm. This is B<SHA1> for both RSA and DSA keys.
The I<certs>, I<signcert> and I<pkey> parameters can all be
NULL if the B<PKCS7_PARTIAL> flag is set. One or more signers can be added
using the function PKCS7_sign_add_signer(). PKCS7_final() must also be
called to finalize the structure if streaming is not enabled. Alternative
signing digests can also be specified using this method.
If I<signcert> and I<pkey> are NULL then a certificates only
PKCS#7 structure is output.
In versions of OpenSSL before 1.0.0 the I<signcert> and I<pkey> parameters must
not be NULL.
PKCS7_sign() is like PKCS7_sign_ex() except that it uses default values of
NULL for the library context I<libctx> and the property query I<propq>.
-This is retained for API backward compatibiliy.
+This is retained for API backward compatibility.
=head1 BUGS
Some advanced attributes such as counter signatures are not supported.
=head1 RETURN VALUES
PKCS7_sign_ex() and PKCS7_sign() return either a valid PKCS7 structure
or NULL if an error occurred. The error can be obtained from ERR_get_error(3).
=head1 SEE ALSO
L<ERR_get_error(3)>, L<PKCS7_verify(3)>
=head1 HISTORY
The function PKCS7_sign_ex() was added in OpenSSL 3.0.
The B<PKCS7_PARTIAL> flag, and the ability for I<certs>, I<signcert>,
and I<pkey> parameters to be NULL were added in OpenSSL 1.0.0.
The B<PKCS7_STREAM> flag was added in OpenSSL 1.0.0.
=head1 COPYRIGHT
-Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CTX_set_options.pod b/doc/man3/SSL_CTX_set_options.pod
index 08522522cd0b..176f8d25fc31 100644
--- a/doc/man3/SSL_CTX_set_options.pod
+++ b/doc/man3/SSL_CTX_set_options.pod
@@ -1,462 +1,466 @@
=pod
=head1 NAME
SSL_CTX_set_options, SSL_set_options, SSL_CTX_clear_options,
SSL_clear_options, SSL_CTX_get_options, SSL_get_options,
SSL_get_secure_renegotiation_support - manipulate SSL options
=head1 SYNOPSIS
#include <openssl/ssl.h>
uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t options);
uint64_t SSL_set_options(SSL *ssl, uint64_t options);
uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t options);
uint64_t SSL_clear_options(SSL *ssl, uint64_t options);
uint64_t SSL_CTX_get_options(const SSL_CTX *ctx);
uint64_t SSL_get_options(const SSL *ssl);
long SSL_get_secure_renegotiation_support(SSL *ssl);
=head1 DESCRIPTION
SSL_CTX_set_options() adds the options set via bit-mask in B<options> to B<ctx>.
Options already set before are not cleared!
SSL_set_options() adds the options set via bit-mask in B<options> to B<ssl>.
Options already set before are not cleared!
SSL_CTX_clear_options() clears the options set via bit-mask in B<options>
to B<ctx>.
SSL_clear_options() clears the options set via bit-mask in B<options> to B<ssl>.
SSL_CTX_get_options() returns the options set for B<ctx>.
SSL_get_options() returns the options set for B<ssl>.
SSL_get_secure_renegotiation_support() indicates whether the peer supports
secure renegotiation.
Note, this is implemented via a macro.
=head1 NOTES
The behaviour of the SSL library can be changed by setting several options.
The options are coded as bit-masks and can be combined by a bitwise B<or>
operation (|).
SSL_CTX_set_options() and SSL_set_options() affect the (external)
protocol behaviour of the SSL library. The (internal) behaviour of
the API can be changed by using the similar
L<SSL_CTX_set_mode(3)> and SSL_set_mode() functions.
During a handshake, the option settings of the SSL object are used. When
a new SSL object is created from a context using SSL_new(), the current
option setting is copied. Changes to B<ctx> do not affect already created
SSL objects. SSL_clear() does not affect the settings.
The following B<bug workaround> options are available:
=over 4
=item SSL_OP_CRYPTOPRO_TLSEXT_BUG
Add server-hello extension from the early version of cryptopro draft
when GOST ciphersuite is negotiated. Required for interoperability with CryptoPro
CSP 3.x.
=item SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol
vulnerability affecting CBC ciphers, which cannot be handled by some
broken SSL implementations. This option has no effect for connections
using other ciphers.
=item SSL_OP_SAFARI_ECDHE_ECDSA_BUG
Don't prefer ECDHE-ECDSA ciphers when the client appears to be Safari on OS X.
OS X 10.8..10.8.3 has broken support for ECDHE-ECDSA ciphers.
=item SSL_OP_TLSEXT_PADDING
Adds a padding extension to ensure the ClientHello size is never between
256 and 511 bytes in length. This is needed as a workaround for some
implementations.
=item SSL_OP_ALL
All of the above bug workarounds.
=back
It is usually safe to use B<SSL_OP_ALL> to enable the bug workaround
options if compatibility with somewhat broken implementations is
desired.
The following B<modifying> options are available:
=over 4
=item SSL_OP_ALLOW_CLIENT_RENEGOTIATION
Client-initiated renegotiation is disabled by default. Use
this option to enable it.
=item SSL_OP_ALLOW_NO_DHE_KEX
In TLSv1.3 allow a non-(ec)dhe based key exchange mode on resumption. This means
that there will be no forward secrecy for the resumed session.
=item SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
Allow legacy insecure renegotiation between OpenSSL and unpatched clients or
servers. See the B<SECURE RENEGOTIATION> section for more details.
=item SSL_OP_CIPHER_SERVER_PREFERENCE
When choosing a cipher, use the server's preferences instead of the client
preferences. When not set, the SSL server will always follow the clients
preferences. When set, the SSL/TLS server will choose following its
own preferences.
=item SSL_OP_CISCO_ANYCONNECT
Use Cisco's version identifier of DTLS_BAD_VER when establishing a DTLSv1
connection. Only available when using the deprecated DTLSv1_client_method() API.
=item SSL_OP_CLEANSE_PLAINTEXT
By default TLS connections keep a copy of received plaintext
application data in a static buffer until it is overwritten by the
next portion of data. When enabling SSL_OP_CLEANSE_PLAINTEXT
deciphered application data is cleansed by calling OPENSSL_cleanse(3)
after passing data to the application. Data is also cleansed when
releasing the connection (e.g. L<SSL_free(3)>).
Since OpenSSL only cleanses internal buffers, the application is still
responsible for cleansing all other buffers. Most notably, this
applies to buffers passed to functions like L<SSL_read(3)>,
L<SSL_peek(3)> but also like L<SSL_write(3)>.
=item SSL_OP_COOKIE_EXCHANGE
Turn on Cookie Exchange as described in RFC4347 Section 4.2.1. Only affects
DTLS connections.
=item SSL_OP_DISABLE_TLSEXT_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 SSL_OP_ENABLE_KTLS
Enable the use of kernel TLS. In order to benefit from kernel TLS OpenSSL must
have been compiled with support for it, and it must be supported by the
negotiated ciphersuites and extensions. The specific ciphersuites and extensions
that are supported may vary by platform and kernel version.
The kernel TLS data-path implements the record layer, and the encryption
algorithm. The kernel will utilize the best hardware
available for encryption. Using the kernel data-path should reduce the memory
footprint of OpenSSL because no buffering is required. Also, the throughput
should improve because data copy is avoided when user data is encrypted into
kernel memory instead of the usual encrypt then copy to kernel.
Kernel TLS might not support all the features of OpenSSL. For instance,
renegotiation, and setting the maximum fragment size is not possible as of
Linux 4.20.
Note that with kernel TLS enabled some cryptographic operations are performed
by the kernel directly and not via any available OpenSSL Providers. This might
be undesirable if, for example, the application requires all cryptographic
operations to be performed by the FIPS provider.
=item SSL_OP_ENABLE_MIDDLEBOX_COMPAT
If set then dummy Change Cipher Spec (CCS) messages are sent in TLSv1.3. This
has the effect of making TLSv1.3 look more like TLSv1.2 so that middleboxes that
do not understand TLSv1.3 will not drop the connection. Regardless of whether
this option is set or not CCS messages received from the peer will always be
ignored in TLSv1.3. This option is set by default. To switch it off use
SSL_clear_options(). A future version of OpenSSL may not set this by default.
=item SSL_OP_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.
You should only enable this option if the protocol running over TLS
can detect a truncation attack itself, and that the application is checking for
that truncation attack.
For more information on shutting down a connection, see L<SSL_shutdown(3)>.
=item SSL_OP_LEGACY_SERVER_CONNECT
Allow legacy insecure renegotiation between OpenSSL and unpatched servers
B<only>. See the B<SECURE RENEGOTIATION> section for more details.
=item SSL_OP_NO_ANTI_REPLAY
By default, when a server is configured for early data (i.e., max_early_data > 0),
OpenSSL will switch on replay protection. See L<SSL_read_early_data(3)> for a
description of the replay protection feature. Anti-replay measures are required
to comply with the TLSv1.3 specification. Some applications may be able to
mitigate the replay risks in other ways and in such cases the built in OpenSSL
functionality is not required. Those applications can turn this feature off by
-setting this option. This is a server-side opton only. It is ignored by
+setting this option. This is a server-side option only. It is ignored by
clients.
=item SSL_OP_NO_COMPRESSION
Do not use compression even if it is supported. This option is set by default.
To switch it off use SSL_clear_options().
=item SSL_OP_NO_ENCRYPT_THEN_MAC
Normally clients and servers will transparently attempt to negotiate the
RFC7366 Encrypt-then-MAC option on TLS and DTLS connection.
If this option is set, Encrypt-then-MAC is disabled. Clients will not
propose, and servers will not accept the extension.
=item SSL_OP_NO_EXTENDED_MASTER_SECRET
Normally clients and servers will transparently attempt to negotiate the
RFC7627 Extended Master Secret option on TLS and DTLS connection.
If this option is set, Extended Master Secret is disabled. Clients will
not propose, and servers will not accept the extension.
=item SSL_OP_NO_QUERY_MTU
Do not query the MTU. Only affects DTLS connections.
=item SSL_OP_NO_RENEGOTIATION
Disable all renegotiation in TLSv1.2 and earlier. Do not send HelloRequest
messages, and ignore renegotiation requests via ClientHello.
=item SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
When performing renegotiation as a server, always start a new session
(i.e., session resumption requests are only accepted in the initial
handshake). This option is not needed for clients.
=item SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1, SSL_OP_NO_TLSv1_1,
SSL_OP_NO_TLSv1_2, SSL_OP_NO_TLSv1_3, SSL_OP_NO_DTLSv1, SSL_OP_NO_DTLSv1_2
These options turn off the SSLv3, TLSv1, TLSv1.1, TLSv1.2 or TLSv1.3 protocol
versions with TLS or the DTLSv1, DTLSv1.2 versions with DTLS,
respectively.
As of OpenSSL 1.1.0, these options are deprecated, use
L<SSL_CTX_set_min_proto_version(3)> and
L<SSL_CTX_set_max_proto_version(3)> instead.
=item SSL_OP_NO_TICKET
SSL/TLS supports two mechanisms for resuming sessions: session ids and stateless
session tickets.
When using session ids a copy of the session information is
cached on the server and a unique id is sent to the client. When the client
wishes to resume it provides the unique id so that the server can retrieve the
session information from its cache.
When using stateless session tickets the server uses a session ticket encryption
key to encrypt the session information. This encrypted data is sent to the
client as a "ticket". When the client wishes to resume it sends the encrypted
data back to the server. The server uses its key to decrypt the data and resume
the session. In this way the server can operate statelessly - no session
information needs to be cached locally.
The TLSv1.3 protocol only supports tickets and does not directly support session
ids. However, OpenSSL allows two modes of ticket operation in TLSv1.3: stateful
and stateless. Stateless tickets work the same way as in TLSv1.2 and below.
Stateful tickets mimic the session id behaviour available in TLSv1.2 and below.
The session information is cached on the server and the session id is wrapped up
in a ticket and sent back to the client. When the client wishes to resume, it
presents a ticket in the same way as for stateless tickets. The server can then
extract the session id from the ticket and retrieve the session information from
its cache.
By default OpenSSL will use stateless tickets. The SSL_OP_NO_TICKET option will
cause stateless tickets to not be issued. In TLSv1.2 and below this means no
ticket gets sent to the client at all. In TLSv1.3 a stateful ticket will be
sent. This is a server-side option only.
In TLSv1.3 it is possible to suppress all tickets (stateful and stateless) from
being sent by calling L<SSL_CTX_set_num_tickets(3)> or
L<SSL_set_num_tickets(3)>.
=item SSL_OP_PRIORITIZE_CHACHA
When SSL_OP_CIPHER_SERVER_PREFERENCE is set, temporarily reprioritize
ChaCha20-Poly1305 ciphers to the top of the server cipher list if a
ChaCha20-Poly1305 cipher is at the top of the client cipher list. This helps
those clients (e.g. mobile) use ChaCha20-Poly1305 if that cipher is anywhere
in the server cipher list; but still allows other clients to use AES and other
ciphers. Requires B<SSL_OP_CIPHER_SERVER_PREFERENCE>.
=item SSL_OP_TLS_ROLLBACK_BUG
Disable version rollback attack detection.
During the client key exchange, the client must send the same information
about acceptable SSL/TLS protocol levels as during the first hello. Some
clients violate this rule by adapting to the server's answer. (Example:
the client sends a SSLv2 hello and accepts up to SSLv3.1=TLSv1, the server
only understands up to SSLv3. In this case the client must still use the
same SSLv3.1=TLSv1 announcement. Some clients step down to SSLv3 with respect
to the server's answer and violate the version rollback protection.)
=back
The following options no longer have any effect but their identifiers are
retained for compatibility purposes:
=over 4
=item SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
=item SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
=item SSL_OP_SSLEAY_080_CLIENT_DH_BUG
=item SSL_OP_TLS_D5_BUG
=item SSL_OP_TLS_BLOCK_PADDING_BUG
=item SSL_OP_MSIE_SSLV2_RSA_PADDING
=item SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
=item SSL_OP_MICROSOFT_SESS_ID_BUG
=item SSL_OP_NETSCAPE_CHALLENGE_BUG
=item SSL_OP_PKCS1_CHECK_1
=item SSL_OP_PKCS1_CHECK_2
=item SSL_OP_SINGLE_DH_USE
=item SSL_OP_SINGLE_ECDH_USE
=item SSL_OP_EPHEMERAL_RSA
+=item SSL_OP_NETSCAPE_CA_DN_BUG
+
+=item SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
+
=back
=head1 SECURE RENEGOTIATION
OpenSSL always attempts to use secure renegotiation as
described in RFC5746. This counters the prefix attack described in
CVE-2009-3555 and elsewhere.
This attack has far reaching consequences which application writers should be
aware of. In the description below an implementation supporting secure
renegotiation is referred to as I<patched>. A server not supporting secure
renegotiation is referred to as I<unpatched>.
The following sections describe the operations permitted by OpenSSL's secure
renegotiation implementation.
=head2 Patched client and server
Connections and renegotiation are always permitted by OpenSSL implementations.
=head2 Unpatched client and patched OpenSSL server
The initial connection succeeds but client renegotiation is denied by the
server with a B<no_renegotiation> warning alert if TLS v1.0 is used or a fatal
B<handshake_failure> alert in SSL v3.0.
If the patched OpenSSL server attempts to renegotiate a fatal
B<handshake_failure> alert is sent. This is because the server code may be
unaware of the unpatched nature of the client.
If the option B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION> is set then
renegotiation B<always> succeeds.
=head2 Patched OpenSSL client and unpatched server
If the option B<SSL_OP_LEGACY_SERVER_CONNECT> or
B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION> is set then initial connections
and renegotiation between patched OpenSSL clients and unpatched servers
succeeds. If neither option is set then initial connections to unpatched
servers will fail.
Setting the option B<SSL_OP_LEGACY_SERVER_CONNECT> has security implications;
clients that are willing to connect to servers that do not implement
RFC 5746 secure renegotiation are subject to attacks such as
CVE-2009-3555.
OpenSSL client applications wishing to ensure they can connect to unpatched
servers should always B<set> B<SSL_OP_LEGACY_SERVER_CONNECT>
OpenSSL client applications that want to ensure they can B<not> connect to
unpatched servers (and thus avoid any security issues) should always B<clear>
B<SSL_OP_LEGACY_SERVER_CONNECT> using SSL_CTX_clear_options() or
SSL_clear_options().
The difference between the B<SSL_OP_LEGACY_SERVER_CONNECT> and
B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION> options is that
B<SSL_OP_LEGACY_SERVER_CONNECT> enables initial connections and secure
renegotiation between OpenSSL clients and unpatched servers B<only>, while
B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION> allows initial connections
and renegotiation between OpenSSL and unpatched clients or servers.
=head1 RETURN VALUES
SSL_CTX_set_options() and SSL_set_options() return the new options bit-mask
after adding B<options>.
SSL_CTX_clear_options() and SSL_clear_options() return the new options bit-mask
after clearing B<options>.
SSL_CTX_get_options() and SSL_get_options() return the current bit-mask.
SSL_get_secure_renegotiation_support() returns 1 is the peer supports
secure renegotiation and 0 if it does not.
=head1 SEE ALSO
L<ssl(7)>, L<SSL_new(3)>, L<SSL_clear(3)>, L<SSL_shutdown(3)>
L<SSL_CTX_set_tmp_dh_callback(3)>,
L<SSL_CTX_set_min_proto_version(3)>,
L<openssl-dhparam(1)>
=head1 HISTORY
The attempt to always try to use secure renegotiation was added in
OpenSSL 0.9.8m.
The B<SSL_OP_PRIORITIZE_CHACHA> and B<SSL_OP_NO_RENEGOTIATION> options
were added in OpenSSL 1.1.1.
The B<SSL_OP_NO_EXTENDED_MASTER_SECRET> and B<SSL_OP_IGNORE_UNEXPECTED_EOF>
options were added in OpenSSL 3.0.
The B<SSL_OP_> constants and the corresponding parameter and return values
of the affected functions were changed to C<uint64_t> type in OpenSSL 3.0.
For that reason it is no longer possible use the B<SSL_OP_> macro values
in preprocessor C<#if> conditions. However it is still possible to test
whether these macros are defined or not.
=head1 COPYRIGHT
-Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-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/doc/man3/SSL_CTX_set_split_send_fragment.pod b/doc/man3/SSL_CTX_set_split_send_fragment.pod
index 5097404398b2..2231f5b127e5 100644
--- a/doc/man3/SSL_CTX_set_split_send_fragment.pod
+++ b/doc/man3/SSL_CTX_set_split_send_fragment.pod
@@ -1,189 +1,192 @@
=pod
=head1 NAME
SSL_CTX_set_max_send_fragment, SSL_set_max_send_fragment,
SSL_CTX_set_split_send_fragment, SSL_set_split_send_fragment,
SSL_CTX_set_max_pipelines, SSL_set_max_pipelines,
SSL_CTX_set_default_read_buffer_len, SSL_set_default_read_buffer_len,
SSL_CTX_set_tlsext_max_fragment_length,
SSL_set_tlsext_max_fragment_length,
SSL_SESSION_get_max_fragment_length - Control fragment size settings and pipelining operations
=head1 SYNOPSIS
#include <openssl/ssl.h>
long SSL_CTX_set_max_send_fragment(SSL_CTX *ctx, long);
long SSL_set_max_send_fragment(SSL *ssl, long m);
long SSL_CTX_set_max_pipelines(SSL_CTX *ctx, long m);
long SSL_set_max_pipelines(SSL_CTX *ssl, long m);
long SSL_CTX_set_split_send_fragment(SSL_CTX *ctx, long m);
long SSL_set_split_send_fragment(SSL *ssl, long m);
void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len);
void SSL_set_default_read_buffer_len(SSL *s, size_t len);
int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode);
int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode);
uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *session);
=head1 DESCRIPTION
Some engines are able to process multiple simultaneous crypto operations. This
capability could be utilised to parallelise the processing of a single
connection. For example a single write can be split into multiple records and
each one encrypted independently and in parallel. Note: this will only work in
TLS1.1+. There is no support in SSLv3, TLSv1.0 or DTLS (any version). This
capability is known as "pipelining" within OpenSSL.
In order to benefit from the pipelining capability. You need to have an engine
that provides ciphers that support this. The OpenSSL "dasync" engine provides
AES128-SHA based ciphers that have this capability. However, these are for
development and test purposes only.
SSL_CTX_set_max_send_fragment() and SSL_set_max_send_fragment() set the
B<max_send_fragment> parameter for SSL_CTX and SSL objects respectively. This
value restricts the amount of plaintext bytes that will be sent in any one
SSL/TLS record. By default its value is SSL3_RT_MAX_PLAIN_LENGTH (16384). These
functions will only accept a value in the range 512 - SSL3_RT_MAX_PLAIN_LENGTH.
SSL_CTX_set_max_pipelines() and SSL_set_max_pipelines() set the maximum number
of pipelines that will be used at any one time. This value applies to both
"read" pipelining and "write" pipelining. By default only one pipeline will be
used (i.e. normal non-parallel operation). The number of pipelines set must be
in the range 1 - SSL_MAX_PIPELINES (32). Setting this to a value > 1 will also
automatically turn on "read_ahead" (see L<SSL_CTX_set_read_ahead(3)>). This is
-explained further below. OpenSSL will only every use more than one pipeline if
+explained further below. OpenSSL will only ever use more than one pipeline if
a cipher suite is negotiated that uses a pipeline capable cipher provided by an
engine.
Pipelining operates slightly differently for reading encrypted data compared to
writing encrypted data. SSL_CTX_set_split_send_fragment() and
SSL_set_split_send_fragment() define how data is split up into pipelines when
writing encrypted data. The number of pipelines used will be determined by the
amount of data provided to the SSL_write_ex() or SSL_write() call divided by
B<split_send_fragment>.
For example if B<split_send_fragment> is set to 2000 and B<max_pipelines> is 4
then:
SSL_write/SSL_write_ex called with 0-2000 bytes == 1 pipeline used
SSL_write/SSL_write_ex called with 2001-4000 bytes == 2 pipelines used
SSL_write/SSL_write_ex called with 4001-6000 bytes == 3 pipelines used
SSL_write/SSL_write_ex called with 6001+ bytes == 4 pipelines used
B<split_send_fragment> must always be less than or equal to
B<max_send_fragment>. By default it is set to be equal to B<max_send_fragment>.
This will mean that the same number of records will always be created as would
have been created in the non-parallel case, although the data will be
apportioned differently. In the parallel case data will be spread equally
between the pipelines.
Read pipelining is controlled in a slightly different way than with write
pipelining. While reading we are constrained by the number of records that the
peer (and the network) can provide to us in one go. The more records we can get
in one go the more opportunity we have to parallelise the processing. As noted
above when setting B<max_pipelines> to a value greater than one, B<read_ahead>
is automatically set. The B<read_ahead> parameter causes OpenSSL to attempt to
read as much data into the read buffer as the network can provide and will fit
into the buffer. Without this set data is read into the read buffer one record
at a time. The more data that can be read, the more opportunity there is for
parallelising the processing at the cost of increased memory overhead per
connection. Setting B<read_ahead> can impact the behaviour of the SSL_pending()
-function (see L<SSL_pending(3)>).
+function (see L<SSL_pending(3)>). In addition the default size of the internal
+read buffer is multiplied by the number of pipelines available to ensure that we
+can read multiple records in one go. This can therefore have a significant
+impact on memory usage.
The SSL_CTX_set_default_read_buffer_len() and SSL_set_default_read_buffer_len()
functions control the size of the read buffer that will be used. The B<len>
parameter sets the size of the buffer. The value will only be used if it is
greater than the default that would have been used anyway. The normal default
value depends on a number of factors but it will be at least
SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_MAX_ENCRYPTED_OVERHEAD (16704) bytes.
SSL_CTX_set_tlsext_max_fragment_length() sets the default maximum fragment
length negotiation mode via value B<mode> to B<ctx>.
This setting affects only SSL instances created after this function is called.
It affects the client-side as only its side may initiate this extension use.
SSL_set_tlsext_max_fragment_length() sets the maximum fragment length
negotiation mode via value B<mode> to B<ssl>.
This setting will be used during a handshake when extensions are exchanged
between client and server.
So it only affects SSL sessions created after this function is called.
It affects the client-side as only its side may initiate this extension use.
SSL_SESSION_get_max_fragment_length() gets the maximum fragment length
negotiated in B<session>.
=head1 RETURN VALUES
All non-void functions return 1 on success and 0 on failure.
=head1 NOTES
The Maximum Fragment Length extension support is optional on the server side.
If the server does not support this extension then
SSL_SESSION_get_max_fragment_length() will return:
TLSEXT_max_fragment_length_DISABLED.
The following modes are available:
=over 4
=item TLSEXT_max_fragment_length_DISABLED
Disables Maximum Fragment Length Negotiation (default).
=item TLSEXT_max_fragment_length_512
Sets Maximum Fragment Length to 512 bytes.
=item TLSEXT_max_fragment_length_1024
Sets Maximum Fragment Length to 1024.
=item TLSEXT_max_fragment_length_2048
Sets Maximum Fragment Length to 2048.
=item TLSEXT_max_fragment_length_4096
Sets Maximum Fragment Length to 4096.
=back
With the exception of SSL_CTX_set_default_read_buffer_len()
SSL_set_default_read_buffer_len(), SSL_CTX_set_tlsext_max_fragment_length(),
SSL_set_tlsext_max_fragment_length() and SSL_SESSION_get_max_fragment_length()
all these functions are implemented using macros.
=head1 SEE ALSO
L<ssl(7)>,
L<SSL_CTX_set_read_ahead(3)>, L<SSL_pending(3)>
=head1 HISTORY
The SSL_CTX_set_max_pipelines(), SSL_set_max_pipelines(),
SSL_CTX_set_split_send_fragment(), SSL_set_split_send_fragment(),
SSL_CTX_set_default_read_buffer_len() and SSL_set_default_read_buffer_len()
functions were added in OpenSSL 1.1.0.
The SSL_CTX_set_tlsext_max_fragment_length(), SSL_set_tlsext_max_fragment_length()
and SSL_SESSION_get_max_fragment_length() functions were added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+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
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_SESSION_free.pod b/doc/man3/SSL_SESSION_free.pod
index 74c6ec2a29cb..4af750a358ba 100644
--- a/doc/man3/SSL_SESSION_free.pod
+++ b/doc/man3/SSL_SESSION_free.pod
@@ -1,87 +1,89 @@
=pod
=head1 NAME
SSL_SESSION_new,
SSL_SESSION_dup,
SSL_SESSION_up_ref,
SSL_SESSION_free - create, free and manage SSL_SESSION structures
=head1 SYNOPSIS
#include <openssl/ssl.h>
SSL_SESSION *SSL_SESSION_new(void);
SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src);
int SSL_SESSION_up_ref(SSL_SESSION *ses);
void SSL_SESSION_free(SSL_SESSION *session);
=head1 DESCRIPTION
SSL_SESSION_new() creates a new SSL_SESSION structure and returns a pointer to
it.
-SSL_SESSION_dup() copies the contents of the SSL_SESSION structure in B<src>
-and returns a pointer to it.
+SSL_SESSION_dup() creates a new SSL_SESSION structure that is a copy of B<src>.
+The copy is not owned by any cache that B<src> may have been in.
SSL_SESSION_up_ref() increments the reference count on the given SSL_SESSION
structure.
SSL_SESSION_free() decrements the reference count of B<session> and removes
the B<SSL_SESSION> structure pointed to by B<session> and frees up the allocated
memory, if the reference count has reached 0.
If B<session> is NULL nothing is done.
=head1 NOTES
SSL_SESSION objects are allocated, when a TLS/SSL handshake operation
is successfully completed. Depending on the settings, see
L<SSL_CTX_set_session_cache_mode(3)>,
the SSL_SESSION objects are internally referenced by the SSL_CTX and
linked into its session cache. SSL objects may be using the SSL_SESSION object;
as a session may be reused, several SSL objects may be using one SSL_SESSION
object at the same time. It is therefore crucial to keep the reference
count (usage information) correct and not delete a SSL_SESSION object
that is still used, as this may lead to program failures due to
dangling pointers. These failures may also appear delayed, e.g.
when an SSL_SESSION object was completely freed as the reference count
incorrectly became 0, but it is still referenced in the internal
session cache and the cache list is processed during a
L<SSL_CTX_flush_sessions(3)> operation.
SSL_SESSION_free() must only be called for SSL_SESSION objects, for
which the reference count was explicitly incremented (e.g.
by calling SSL_get1_session(), see L<SSL_get_session(3)>)
or when the SSL_SESSION object was generated outside a TLS handshake
operation, e.g. by using L<d2i_SSL_SESSION(3)>.
It must not be called on other SSL_SESSION objects, as this would cause
incorrect reference counts and therefore program failures.
=head1 RETURN VALUES
SSL_SESSION_new returns a pointer to the newly allocated SSL_SESSION structure
or NULL on error.
+SSL_SESSION_dup returns a pointer to the new copy or NULL on error.
+
SSL_SESSION_up_ref returns 1 on success or 0 on error.
=head1 SEE ALSO
L<ssl(7)>, L<SSL_get_session(3)>,
L<SSL_CTX_set_session_cache_mode(3)>,
L<SSL_CTX_flush_sessions(3)>,
L<d2i_SSL_SESSION(3)>
=head1 HISTORY
The SSL_SESSION_dup() function was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man3/X509_STORE_CTX_get_error.pod b/doc/man3/X509_STORE_CTX_get_error.pod
index d0036b38b6a6..c992d5da27de 100644
--- a/doc/man3/X509_STORE_CTX_get_error.pod
+++ b/doc/man3/X509_STORE_CTX_get_error.pod
@@ -1,483 +1,500 @@
=pod
=head1 NAME
X509_STORE_CTX_get_error, X509_STORE_CTX_set_error,
X509_STORE_CTX_get_error_depth, X509_STORE_CTX_set_error_depth,
X509_STORE_CTX_get_current_cert, X509_STORE_CTX_set_current_cert,
X509_STORE_CTX_get0_cert, X509_STORE_CTX_get1_chain,
X509_verify_cert_error_string - get or set certificate verification status
information
=head1 SYNOPSIS
#include <openssl/x509.h>
int X509_STORE_CTX_get_error(const X509_STORE_CTX *ctx);
void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s);
int X509_STORE_CTX_get_error_depth(const X509_STORE_CTX *ctx);
void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth);
X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx);
void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x);
X509 *X509_STORE_CTX_get0_cert(const X509_STORE_CTX *ctx);
STACK_OF(X509) *X509_STORE_CTX_get1_chain(const X509_STORE_CTX *ctx);
const char *X509_verify_cert_error_string(long n);
=head1 DESCRIPTION
These functions are typically called after certificate or chain verification
using L<X509_verify_cert(3)> or L<X509_STORE_CTX_verify(3)> has indicated
an error or in a verification callback to determine the nature of an error.
X509_STORE_CTX_get_error() returns the error code of I<ctx>.
See the L</ERROR CODES> section for a full description of all error codes.
It may return a code != X509_V_OK even if X509_verify_cert() did not indicate
an error, likely because a verification callback function has waived the error.
X509_STORE_CTX_set_error() sets the error code of I<ctx> to I<s>. For example
it might be used in a verification callback to set an error based on additional
checks.
X509_STORE_CTX_get_error_depth() returns the I<depth> of the error. This is a
nonnegative integer representing where in the certificate chain the error
occurred. If it is zero it occurred in the end entity certificate, one if
it is the certificate which signed the end entity certificate and so on.
X509_STORE_CTX_set_error_depth() sets the error I<depth>.
This can be used in combination with X509_STORE_CTX_set_error() to set the
depth at which an error condition was detected.
X509_STORE_CTX_get_current_cert() returns the current certificate in
I<ctx>. If an error occurred, the current certificate will be the one
that is most closely related to the error, or possibly NULL if no such
certificate is relevant.
X509_STORE_CTX_set_current_cert() sets the certificate I<x> in I<ctx> which
caused the error.
This value is not intended to remain valid for very long, and remains owned by
the caller.
It may be examined by a verification callback invoked to handle each error
encountered during chain verification and is no longer required after such a
callback.
If a callback wishes the save the certificate for use after it returns, it
needs to increment its reference count via L<X509_up_ref(3)>.
Once such a I<saved> certificate is no longer needed it can be freed with
L<X509_free(3)>.
X509_STORE_CTX_get0_cert() retrieves an internal pointer to the
certificate being verified by the I<ctx>.
X509_STORE_CTX_get1_chain() returns a complete validate chain if a previous
verification is successful. Otherwise the returned chain may be incomplete or
invalid. The returned chain persists after the I<ctx> structure is freed.
When it is no longer needed it should be free up using:
sk_X509_pop_free(chain, X509_free);
X509_verify_cert_error_string() returns a human readable error string for
verification error I<n>.
=head1 RETURN VALUES
X509_STORE_CTX_get_error() returns B<X509_V_OK> or an error code.
X509_STORE_CTX_get_error_depth() returns a nonnegative error depth.
X509_STORE_CTX_get_current_cert() returns the certificate which caused the
error or NULL if no certificate is relevant to the error.
X509_verify_cert_error_string() returns a human readable error string for
verification error I<n>.
=head1 ERROR CODES
A list of error codes and messages is shown below. Some of the
error codes are defined but currently never returned: these are described as
"unused".
=over 4
=item B<X509_V_OK: ok>
The operation was successful.
=item B<X509_V_ERR_UNSPECIFIED: unspecified certificate verification error>
Unspecified error; should not happen.
=item B<X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: unable to get issuer certificate>
The issuer certificate of a locally looked up certificate could not be found.
This normally means the list of trusted certificates is not complete.
To allow any certificate (not only a self-signed one) in the trust store
to terminate the chain the B<X509_V_FLAG_PARTIAL_CHAIN> flag may be set.
=item B<X509_V_ERR_UNABLE_TO_GET_CRL: unable to get certificate CRL>
The CRL of a certificate could not be found.
=item B<X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
unable to decrypt certificate's signature>
The certificate signature could not be decrypted. This means that the actual
signature value could not be determined rather than it not matching the
expected value, this is only meaningful for RSA keys.
=item B<X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
unable to decrypt CRL's signature>
The CRL signature could not be decrypted: this means that the actual signature
value could not be determined rather than it not matching the expected value.
Unused.
=item B<X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
unable to decode issuer public key>
The public key in the certificate C<SubjectPublicKeyInfo> field could
not be read.
=item B<X509_V_ERR_CERT_SIGNATURE_FAILURE: certificate signature failure>
The signature of the certificate is invalid.
=item B<X509_V_ERR_CRL_SIGNATURE_FAILURE: CRL signature failure>
The signature of the CRL is invalid.
=item B<X509_V_ERR_CERT_NOT_YET_VALID: certificate is not yet valid>
The certificate is not yet valid: the C<notBefore> date is after the
current time.
=item B<X509_V_ERR_CERT_HAS_EXPIRED: certificate has expired>
The certificate has expired: that is the C<notAfter> date is before the
current time.
=item B<X509_V_ERR_CRL_NOT_YET_VALID: CRL is not yet valid>
The CRL is not yet valid.
=item B<X509_V_ERR_CRL_HAS_EXPIRED: CRL has expired>
The CRL has expired.
=item B<X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
format error in certificate's notBefore field>
The certificate C<notBefore> field contains an invalid time.
=item B<X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
format error in certificate's notAfter field>
The certificate C<notAfter> field contains an invalid time.
=item B<X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
format error in CRL's lastUpdate field>
The CRL B<lastUpdate> field contains an invalid time.
=item B<X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
format error in CRL's nextUpdate field>
The CRL C<nextUpdate> field contains an invalid time.
=item B<X509_V_ERR_OUT_OF_MEM: out of memory>
An error occurred trying to allocate memory.
=item B<X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: self-signed certificate>
The passed certificate is self-signed and the same certificate cannot be found
in the list of trusted certificates.
=item B<X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
self-signed certificate in certificate chain>
The certificate chain could be built up using the untrusted certificates
but no suitable trust anchor (which typically is a self-signed root certificate)
could be found in the trust store.
=item B<X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
unable to get local issuer certificate>
The issuer certificate could not be found: this occurs if the issuer certificate
of an untrusted certificate cannot be found.
=item B<X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
unable to verify the first certificate>
No signatures could be verified because the chain contains only one certificate
and it is not self-signed and the B<X509_V_FLAG_PARTIAL_CHAIN> flag is not set.
=item B<X509_V_ERR_CERT_CHAIN_TOO_LONG: certificate chain too long>
The certificate chain length is greater than the supplied maximum depth.
=item B<X509_V_ERR_CERT_REVOKED: certificate revoked>
The certificate has been revoked.
-=item B<X509_V_ERR_INVALID_CA: invalid CA certificate>
+=item B<X509_V_ERR_NO_ISSUER_PUBLIC_KEY:
+ issuer certificate doesn't have a public key>
-A CA certificate is invalid. Either it is not a CA or its extensions are not
-consistent with the supplied purpose.
+The issuer certificate does not have a public key.
=item B<X509_V_ERR_PATH_LENGTH_EXCEEDED: path length constraint exceeded>
The basicConstraints path-length parameter has been exceeded.
=item B<X509_V_ERR_INVALID_PURPOSE: unsuitable certificate purpose>
The target certificate cannot be used for the specified purpose.
=item B<X509_V_ERR_CERT_UNTRUSTED: certificate not trusted>
The root CA is not marked as trusted for the specified purpose.
=item B<X509_V_ERR_CERT_REJECTED: certificate rejected>
The root CA is marked to reject the specified purpose.
=item B<X509_V_ERR_SUBJECT_ISSUER_MISMATCH: subject issuer mismatch>
The current candidate issuer certificate was rejected because its subject name
did not match the issuer name of the current certificate.
=item B<X509_V_ERR_AKID_SKID_MISMATCH:
authority and subject key identifier mismatch>
The current candidate issuer certificate was rejected because its subject key
identifier was present and did not match the authority key identifier current
certificate.
=item B<X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
authority and issuer serial number mismatch>
The current candidate issuer certificate was rejected because its issuer name
and serial number was present and did not match the authority key identifier of
the current certificate.
=item B<X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
key usage does not include certificate signing>
The current candidate issuer certificate was rejected because its C<keyUsage>
extension does not permit certificate signing.
+=item B<X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
+unable to get CRL issuer certificate>
+
+Unable to get CRL issuer certificate.
+
+=item B<X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: unhandled critical extension>
+
+Unhandled critical extension.
+
+=item B<X509_V_ERR_KEYUSAGE_NO_CRL_SIGN: key usage does not include CRL signing>
+
+Key usage does not include CRL signing.
+
+=item B<X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: unhandled critical CRL extension>
+
+Unhandled critical CRL extension.
+
+=item B<X509_V_ERR_INVALID_NON_CA: invalid non-CA certificate (has CA markings)>
+
+Invalid non-CA certificate has CA markings.
+
+=item B<X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED:
+proxy path length constraint exceeded>
+
+Proxy path length constraint exceeded.
+
+=item B<X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE:
+key usage does not include digital signature>
+
+Key usage does not include digital signature, and therefore cannot sign
+certificates.
+
+=item B<X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED:
+ proxy certificates not allowed, please set the appropriate flag>
+
+Proxy certificates not allowed unless the B<X509_V_FLAG_ALLOW_PROXY_CERTS> flag
+is set.
+
=item B<X509_V_ERR_INVALID_EXTENSION:
invalid or inconsistent certificate extension>
A certificate extension had an invalid value (for example an incorrect
encoding) or some value inconsistent with other extensions.
=item B<X509_V_ERR_INVALID_POLICY_EXTENSION:
invalid or inconsistent certificate policy extension>
A certificate policies extension had an invalid value (for example an incorrect
encoding) or some value inconsistent with other extensions. This error only
occurs if policy processing is enabled.
=item B<X509_V_ERR_NO_EXPLICIT_POLICY: no explicit policy>
The verification flags were set to require and explicit policy but none was
present.
=item B<X509_V_ERR_DIFFERENT_CRL_SCOPE: different CRL scope>
The only CRLs that could be found did not match the scope of the certificate.
-=item B<X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE: Unsupported extension feature>
+=item B<X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE: unsupported extension feature>
Some feature of a certificate extension is not supported. Unused.
+=item B<X509_V_ERR_UNNESTED_RESOURCE: RFC 3779 resource not subset of parent's resources>
+
+See RFC 3779 for details.
+
=item B<X509_V_ERR_PERMITTED_VIOLATION: permitted subtree violation>
A name constraint violation occurred in the permitted subtrees.
=item B<X509_V_ERR_EXCLUDED_VIOLATION: excluded subtree violation>
A name constraint violation occurred in the excluded subtrees.
=item B<X509_V_ERR_SUBTREE_MINMAX:
name constraints minimum and maximum not supported>
A certificate name constraints extension included a minimum or maximum field:
this is not supported.
+=item B<X509_V_ERR_APPLICATION_VERIFICATION: application verification failure>
+
+An application specific error. This will never be returned unless explicitly
+set by an application callback.
+
=item B<X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE:
unsupported name constraint type>
An unsupported name constraint type was encountered. OpenSSL currently only
supports directory name, DNS name, email and URI types.
=item B<X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX:
unsupported or invalid name constraint syntax>
The format of the name constraint is not recognised: for example an email
address format of a form not mentioned in RFC3280. This could be caused by
a garbage extension or some new feature not currently supported.
+=item B<X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: unsupported or invalid name syntax>
+
+Unsupported or invalid name syntax.
+
=item B<X509_V_ERR_CRL_PATH_VALIDATION_ERROR: CRL path validation error>
An error occurred when attempting to verify the CRL path. This error can only
happen if extended CRL checking is enabled.
-=item B<X509_V_ERR_APPLICATION_VERIFICATION: application verification failure>
-
-An application specific error. This will never be returned unless explicitly
-set by an application callback.
-
-=item B<X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: unable to get CRL issuer certificate>
-
-Unable to get CRL issuer certificate.
-
-=item B<X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: unhandled critical extension>
-
-Unhandled critical extension.
-
-=item B<X509_V_ERR_KEYUSAGE_NO_CRL_SIGN: key usage does not include CRL signing>
-
-Key usage does not include CRL signing.
-
-=item B<X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: unhandled critical CRL extension>
-
-Unhandled critical CRL extension.
-
-=item B<X509_V_ERR_INVALID_NON_CA: invalid non-CA certificate (has CA markings)>
-
-Invalid non-CA certificate has CA markings.
-
-=item B<X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: proxy path length constraint exceeded>
-
-Proxy path length constraint exceeded.
-
-=item B<X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: key usage does not include digital signature>
-
-Key usage does not include digital signature, and therefore cannot sign
-certificates.
-
-=item B<X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: proxy certificates not allowed, please set the appropriate flag>
-
-Proxy certificates not allowed unless the B<X509_V_FLAG_ALLOW_PROXY_CERTS> flag
-is set.
-
-=item B<X509_V_ERR_UNNESTED_RESOURCE: RFC 3779 resource not subset of parent's resources>
-
-See RFC 3779 for details.
-
-=item B<X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: unsupported or invalid name syntax>
-
-Unsupported or invalid name syntax.
-
=item B<X509_V_ERR_PATH_LOOP: path loop>
Path loop.
=item B<X509_V_ERR_HOSTNAME_MISMATCH: hostname mismatch>
Hostname mismatch.
=item B<X509_V_ERR_EMAIL_MISMATCH: email address mismatch>
Email address mismatch.
=item B<X509_V_ERR_IP_ADDRESS_MISMATCH: IP address mismatch>
IP address mismatch.
=item B<X509_V_ERR_DANE_NO_MATCH: no matching DANE TLSA records>
DANE TLSA authentication is enabled, but no TLSA records matched the
certificate chain.
This error is only possible in L<openssl-s_client(1)>.
=item B<X509_V_ERR_EE_KEY_TOO_SMALL: EE certificate key too weak>
EE certificate key too weak.
=item B<X509_V_ERR_CA_KEY_TOO_SMALL: CA certificate key too weak>
CA certificate key too weak.
=item B<X509_V_ERR_CA_MD_TOO_WEAK: CA signature digest algorithm too weak>
CA signature digest algorithm too weak.
=item B<X509_V_ERR_INVALID_CALL: invalid certificate verification context>
Invalid certificate verification context.
=item B<X509_V_ERR_STORE_LOOKUP: issuer certificate lookup error>
Issuer certificate lookup error.
=item B<X509_V_ERR_NO_VALID_SCTS: certificate transparency required, but no valid SCTs found>
Certificate Transparency required, but no valid SCTs found.
=item B<X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION: proxy subject name violation>
Proxy subject name violation.
=item B<X509_V_ERR_OCSP_VERIFY_NEEDED: OCSP verification needed>
Returned by the verify callback to indicate an OCSP verification is needed.
=item B<X509_V_ERR_OCSP_VERIFY_FAILED: OCSP verification failed>
Returned by the verify callback to indicate OCSP verification failed.
=item B<X509_V_ERR_OCSP_CERT_UNKNOWN: OCSP unknown cert>
Returned by the verify callback to indicate that the certificate is not
recognized by the OCSP responder.
-=item B<X509_V_ERR_NO_ISSUER_PUBLIC_KEY: issuer certificate doesn't have a public key>
+=item B<X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM:
+unsupported signature algorithm>
-The issuer certificate does not have a public key.
+Cannot find certificate signature algorithm.
-=item B<X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH: subject signature algorithm and issuer public key algorithm mismatch>
+=item B<X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH:
+subject signature algorithm and issuer public key algorithm mismatch>
The issuer's public key is not of the type required by the signature in
the subject's certificate.
+=item B<X509_V_ERR_SIGNATURE_ALGORITHM_INCONSISTENCY:
+cert info signature and signature algorithm mismatch>
+
+The algorithm given in the certificate info is inconsistent
+ with the one used for the certificate signature.
+
+=item B<X509_V_ERR_INVALID_CA: invalid CA certificate>
+
+A CA certificate is invalid. Either it is not a CA or its extensions are not
+consistent with the supplied purpose.
+
=back
=head1 NOTES
The above functions should be used instead of directly referencing the fields
in the B<X509_VERIFY_CTX> structure.
In versions of OpenSSL before 1.0 the current certificate returned by
X509_STORE_CTX_get_current_cert() was never NULL. Applications should
check the return value before printing out any debugging information relating
to the current certificate.
If an unrecognised error code is passed to X509_verify_cert_error_string() the
numerical value of the unknown code is returned in a static buffer. This is not
thread safe but will never happen unless an invalid code is passed.
=head1 BUGS
Previous versions of this documentation swapped the meaning of the
B<X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT> and
B<X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY> error codes.
=head1 SEE ALSO
L<X509_verify_cert(3)>, L<X509_STORE_CTX_verify(3)>,
L<X509_up_ref(3)>,
L<X509_free(3)>.
=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/doc/man3/X509_VERIFY_PARAM_set_flags.pod b/doc/man3/X509_VERIFY_PARAM_set_flags.pod
index 75a167702296..43c1900bca78 100644
--- a/doc/man3/X509_VERIFY_PARAM_set_flags.pod
+++ b/doc/man3/X509_VERIFY_PARAM_set_flags.pod
@@ -1,412 +1,417 @@
=pod
=head1 NAME
X509_VERIFY_PARAM_set_flags, X509_VERIFY_PARAM_clear_flags,
X509_VERIFY_PARAM_get_flags, X509_VERIFY_PARAM_set_purpose,
X509_VERIFY_PARAM_get_inh_flags, X509_VERIFY_PARAM_set_inh_flags,
X509_VERIFY_PARAM_set_trust, X509_VERIFY_PARAM_set_depth,
X509_VERIFY_PARAM_get_depth, X509_VERIFY_PARAM_set_auth_level,
X509_VERIFY_PARAM_get_auth_level, X509_VERIFY_PARAM_set_time,
X509_VERIFY_PARAM_get_time,
X509_VERIFY_PARAM_add0_policy, X509_VERIFY_PARAM_set1_policies,
X509_VERIFY_PARAM_get0_host,
X509_VERIFY_PARAM_set1_host, X509_VERIFY_PARAM_add1_host,
X509_VERIFY_PARAM_set_hostflags,
X509_VERIFY_PARAM_get_hostflags,
X509_VERIFY_PARAM_get0_peername,
X509_VERIFY_PARAM_get0_email, X509_VERIFY_PARAM_set1_email,
X509_VERIFY_PARAM_set1_ip, X509_VERIFY_PARAM_get1_ip_asc,
X509_VERIFY_PARAM_set1_ip_asc
- X509 verification parameters
=head1 SYNOPSIS
#include <openssl/x509_vfy.h>
int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param,
unsigned long flags);
int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
unsigned long flags);
unsigned long X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM *param);
int X509_VERIFY_PARAM_set_inh_flags(X509_VERIFY_PARAM *param,
uint32_t flags);
uint32_t X509_VERIFY_PARAM_get_inh_flags(const X509_VERIFY_PARAM *param);
int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose);
int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust);
void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t);
time_t X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param);
int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
ASN1_OBJECT *policy);
int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
STACK_OF(ASN1_OBJECT) *policies);
void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth);
int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param);
void X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param,
int auth_level);
int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param);
char *X509_VERIFY_PARAM_get0_host(X509_VERIFY_PARAM *param, int n);
int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
const char *name, size_t namelen);
int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
const char *name, size_t namelen);
void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
unsigned int flags);
unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param);
char *X509_VERIFY_PARAM_get0_peername(const X509_VERIFY_PARAM *param);
char *X509_VERIFY_PARAM_get0_email(X509_VERIFY_PARAM *param);
int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
const char *email, size_t emaillen);
char *X509_VERIFY_PARAM_get1_ip_asc(X509_VERIFY_PARAM *param);
int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
const unsigned char *ip, size_t iplen);
int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc);
=head1 DESCRIPTION
These functions manipulate the B<X509_VERIFY_PARAM> structure associated with
a certificate verification operation.
The X509_VERIFY_PARAM_set_flags() function sets the flags in B<param> by oring
it with B<flags>. See L</VERIFICATION FLAGS> for a complete
description of values the B<flags> parameter can take.
X509_VERIFY_PARAM_get_flags() returns the flags in B<param>.
X509_VERIFY_PARAM_get_inh_flags() returns the inheritance flags in B<param>
which specifies how verification flags are copied from one structure to
another. X509_VERIFY_PARAM_set_inh_flags() sets the inheritance flags.
See the B<INHERITANCE FLAGS> section for a description of these bits.
X509_VERIFY_PARAM_clear_flags() clears the flags B<flags> in B<param>.
X509_VERIFY_PARAM_set_purpose() sets the verification purpose in B<param>
to B<purpose>. This determines the acceptable purpose of the certificate
chain, for example B<X509_PURPOSE_SSL_CLIENT>.
The purpose requirement is cleared if B<purpose> is 0.
X509_VERIFY_PARAM_set_trust() sets the trust setting in B<param> to
B<trust>.
X509_VERIFY_PARAM_set_time() sets the verification time in B<param> to
B<t>. Normally the current time is used.
-X509_VERIFY_PARAM_add0_policy() enables policy checking (it is disabled
-by default) and adds B<policy> to the acceptable policy set.
+X509_VERIFY_PARAM_add0_policy() adds B<policy> to the acceptable policy set.
+Contrary to preexisting documentation of this function it does not enable
+policy checking.
X509_VERIFY_PARAM_set1_policies() enables policy checking (it is disabled
by default) and sets the acceptable policy set to B<policies>. Any existing
policy set is cleared. The B<policies> parameter can be B<NULL> to clear
an existing policy set.
X509_VERIFY_PARAM_set_depth() sets the maximum verification depth to B<depth>.
That is the maximum number of intermediate CA certificates that can appear in a
chain.
A maximal depth chain contains 2 more certificates than the limit, since
neither the end-entity certificate nor the trust-anchor count against this
limit.
Thus a B<depth> limit of 0 only allows the end-entity certificate to be signed
directly by the trust anchor, while with a B<depth> limit of 1 there can be one
intermediate CA certificate between the trust anchor and the end-entity
certificate.
X509_VERIFY_PARAM_set_auth_level() sets the authentication security level to
B<auth_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 level.
The signature algorithm security level is not enforced for the chain's I<trust
anchor> certificate, 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.
X509_VERIFY_PARAM_get0_host() returns the B<n>th expected DNS hostname that has
been set using X509_VERIFY_PARAM_set1_host() or X509_VERIFY_PARAM_add1_host().
To obtain all names start with B<n> = 0 and increment B<n> as long as no NULL
pointer is returned.
X509_VERIFY_PARAM_set1_host() sets the expected DNS hostname to
B<name> clearing any previously specified hostname. If
B<name> is NULL, or empty the list of hostnames is cleared, and
name checks are not performed on the peer certificate. If B<name>
is NUL-terminated, B<namelen> may be zero, otherwise B<namelen>
must be set to the length of B<name>.
When a hostname is specified,
certificate verification automatically invokes L<X509_check_host(3)>
with flags equal to the B<flags> argument given to
X509_VERIFY_PARAM_set_hostflags() (default zero). Applications
are strongly advised to use this interface in preference to explicitly
calling L<X509_check_host(3)>, hostname checks may be out of scope
with the DANE-EE(3) certificate usage, and the internal check will
be suppressed as appropriate when DANE verification is enabled.
When the subject CommonName will not be ignored, whether as a result of the
B<X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT> host flag, or because no DNS subject
alternative names are present in the certificate, any DNS name constraints in
issuer certificates apply to the subject CommonName as well as the subject
alternative name extension.
When the subject CommonName will be ignored, whether as a result of the
B<X509_CHECK_FLAG_NEVER_CHECK_SUBJECT> host flag, or because some DNS subject
alternative names are present in the certificate, DNS name constraints in
issuer certificates will not be applied to the subject DN.
As described in X509_check_host(3) the B<X509_CHECK_FLAG_NEVER_CHECK_SUBJECT>
flag takes precedence over the B<X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT> flag.
X509_VERIFY_PARAM_get_hostflags() returns any host flags previously set via a
call to X509_VERIFY_PARAM_set_hostflags().
X509_VERIFY_PARAM_add1_host() adds B<name> as an additional reference
identifier that can match the peer's certificate. Any previous names
set via X509_VERIFY_PARAM_set1_host() or X509_VERIFY_PARAM_add1_host()
are retained, no change is made if B<name> is NULL or empty. When
multiple names are configured, the peer is considered verified when
any name matches.
X509_VERIFY_PARAM_get0_peername() returns the DNS hostname or subject
CommonName from the peer certificate that matched one of the reference
identifiers. When wildcard matching is not disabled, or when a
reference identifier specifies a parent domain (starts with ".")
rather than a hostname, the peer name may be a wildcard name or a
sub-domain of the reference identifier respectively. The return
string is allocated by the library and is no longer valid once the
associated B<param> argument is freed. Applications must not free
the return value.
X509_VERIFY_PARAM_get0_email() returns the expected RFC822 email address.
X509_VERIFY_PARAM_set1_email() sets the expected RFC822 email address to
B<email>. If B<email> is NUL-terminated, B<emaillen> may be zero, otherwise
B<emaillen> must be set to the length of B<email>. When an email address
is specified, certificate verification automatically invokes
L<X509_check_email(3)>.
X509_VERIFY_PARAM_get1_ip_asc() returns the expected IP address as a string.
The caller is responsible for freeing it.
X509_VERIFY_PARAM_set1_ip() sets the expected IP address to B<ip>.
The B<ip> argument is in binary format, in network byte-order and
B<iplen> must be set to 4 for IPv4 and 16 for IPv6. When an IP
address is specified, certificate verification automatically invokes
L<X509_check_ip(3)>.
X509_VERIFY_PARAM_set1_ip_asc() sets the expected IP address to
B<ipasc>. The B<ipasc> argument is a NUL-terminal ASCII string:
dotted decimal quad for IPv4 and colon-separated hexadecimal for
IPv6. The condensed "::" notation is supported for IPv6 addresses.
=head1 RETURN VALUES
X509_VERIFY_PARAM_set_flags(), X509_VERIFY_PARAM_clear_flags(),
X509_VERIFY_PARAM_set_inh_flags(),
X509_VERIFY_PARAM_set_purpose(), X509_VERIFY_PARAM_set_trust(),
X509_VERIFY_PARAM_add0_policy() X509_VERIFY_PARAM_set1_policies(),
X509_VERIFY_PARAM_set1_host(), X509_VERIFY_PARAM_add1_host(),
X509_VERIFY_PARAM_set1_email(), X509_VERIFY_PARAM_set1_ip() and
X509_VERIFY_PARAM_set1_ip_asc() return 1 for success and 0 for
failure.
X509_VERIFY_PARAM_get0_host(), X509_VERIFY_PARAM_get0_email(), and
X509_VERIFY_PARAM_get1_ip_asc(), return the string pointers pecified above
or NULL if the respective value has not been set or on error.
X509_VERIFY_PARAM_get_flags() returns the current verification flags.
X509_VERIFY_PARAM_get_hostflags() returns any current host flags.
X509_VERIFY_PARAM_get_inh_flags() returns the current inheritance flags.
X509_VERIFY_PARAM_set_time() and X509_VERIFY_PARAM_set_depth() do not return
values.
X509_VERIFY_PARAM_get_depth() returns the current verification depth.
X509_VERIFY_PARAM_get_auth_level() returns the current authentication security
level.
=head1 VERIFICATION FLAGS
The verification flags consists of zero or more of the following flags
ored together.
B<X509_V_FLAG_CRL_CHECK> enables CRL checking for the certificate chain leaf
certificate. An error occurs if a suitable CRL cannot be found.
B<X509_V_FLAG_CRL_CHECK_ALL> enables CRL checking for the entire certificate
chain.
B<X509_V_FLAG_IGNORE_CRITICAL> disables critical extension checking. By default
any unhandled critical extensions in certificates or (if checked) CRLs result
in a fatal error. If this flag is set unhandled critical extensions are
ignored. B<WARNING> setting this option for anything other than debugging
purposes can be a security risk. Finer control over which extensions are
supported can be performed in the verification callback.
The B<X509_V_FLAG_X509_STRICT> flag disables workarounds for some broken
certificates and makes the verification strictly apply B<X509> rules.
B<X509_V_FLAG_ALLOW_PROXY_CERTS> enables proxy certificate verification.
B<X509_V_FLAG_POLICY_CHECK> enables certificate policy checking, by default
no policy checking is performed. Additional information is sent to the
verification callback relating to policy checking.
B<X509_V_FLAG_EXPLICIT_POLICY>, B<X509_V_FLAG_INHIBIT_ANY> and
B<X509_V_FLAG_INHIBIT_MAP> set the B<require explicit policy>, B<inhibit any
policy> and B<inhibit policy mapping> flags respectively as defined in
B<RFC3280>. Policy checking is automatically enabled if any of these flags
are set.
If B<X509_V_FLAG_NOTIFY_POLICY> is set and the policy checking is successful
a special status code is set to the verification callback. This permits it
to examine the valid policy tree and perform additional checks or simply
log it for debugging purposes.
By default some additional features such as indirect CRLs and CRLs signed by
different keys are disabled. If B<X509_V_FLAG_EXTENDED_CRL_SUPPORT> is set
they are enabled.
If B<X509_V_FLAG_USE_DELTAS> is set delta CRLs (if present) are used to
determine certificate status. If not set deltas are ignored.
B<X509_V_FLAG_CHECK_SS_SIGNATURE> requests checking 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 I<keyCertSign> bit.
By default this check is disabled because it doesn't
add any additional security but in some cases applications might want to
check the signature anyway. A side effect of not checking the self-signature
of such a certificate is that disabled or unsupported message digests used for
the signature are not treated as fatal errors.
When B<X509_V_FLAG_TRUSTED_FIRST> is set, which is always the case since
OpenSSL 1.1.0, construction of the certificate chain
in L<X509_verify_cert(3)> searches the trust store for issuer certificates
before searching the provided untrusted certificates.
Local issuer certificates are often more likely to satisfy local security
requirements and lead to a locally trusted root.
This is especially important when some certificates in the trust store have
explicit trust settings (see "TRUST SETTINGS" in L<openssl-x509(1)>).
The B<X509_V_FLAG_NO_ALT_CHAINS> flag could have been used before OpenSSL 1.1.0
to suppress checking for alternative chains.
By default, unless B<X509_V_FLAG_TRUSTED_FIRST> is set, when building a
certificate chain, if the first certificate chain found is not trusted, then
OpenSSL will attempt to replace untrusted certificates supplied by the peer
with certificates from the trust store to see if an alternative chain can be
found that is trusted.
As of OpenSSL 1.1.0, with B<X509_V_FLAG_TRUSTED_FIRST> always set, this option
has no effect.
The B<X509_V_FLAG_PARTIAL_CHAIN> flag causes non-self-signed certificates in the
trust store to be treated as trust anchors, in the same way as self-signed
root CA certificates.
This makes it possible to trust self-issued certificates as well as certificates
issued by an intermediate CA without having to trust their ancestor root CA.
With OpenSSL 1.1.0 and later and B<X509_V_FLAG_PARTIAL_CHAIN> set, chain
construction stops as soon as the first certificate contained in the trust store
is added to the chain, whether that certificate is a self-signed "root"
certificate or a not self-signed "intermediate" or self-issued certificate.
Thus, when an intermediate certificate is found in the trust store, the
verified chain passed to callbacks may be shorter than it otherwise would
be without the B<X509_V_FLAG_PARTIAL_CHAIN> flag.
The B<X509_V_FLAG_NO_CHECK_TIME> flag suppresses checking the validity period
of certificates and CRLs against the current time. If X509_VERIFY_PARAM_set_time()
is used to specify a verification time, the check is not suppressed.
=head1 INHERITANCE FLAGS
These flags specify how parameters are "inherited" from one structure to
another.
If B<X509_VP_FLAG_ONCE> is set then the current setting is zeroed
after the next call.
If B<X509_VP_FLAG_LOCKED> is set then no values are copied. This overrides
all of the following flags.
If B<X509_VP_FLAG_DEFAULT> is set then anything set in the source is copied
to the destination. Effectively the values in "to" become default values
which will be used only if nothing new is set in "from". This is the
default.
If B<X509_VP_FLAG_OVERWRITE> is set then all value are copied across whether
they are set or not. Flags is still Ored though.
If B<X509_VP_FLAG_RESET_FLAGS> is set then the flags value is copied instead
of ORed.
=head1 NOTES
The above functions should be used to manipulate verification parameters
instead of functions which work in specific structures such as
X509_STORE_CTX_set_flags() which are likely to be deprecated in a future
release.
=head1 BUGS
Delta CRL checking is currently primitive. Only a single delta can be used and
(partly due to limitations of B<X509_STORE>) constructed CRLs are not
maintained.
If CRLs checking is enable CRLs are expected to be available in the
corresponding B<X509_STORE> structure. No attempt is made to download
CRLs from the CRL distribution points extension.
=head1 EXAMPLES
Enable CRL checking when performing certificate verification during SSL
connections associated with an B<SSL_CTX> structure B<ctx>:
X509_VERIFY_PARAM *param;
param = X509_VERIFY_PARAM_new();
X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
SSL_CTX_set1_param(ctx, param);
X509_VERIFY_PARAM_free(param);
=head1 SEE ALSO
L<X509_verify_cert(3)>,
L<X509_check_host(3)>,
L<X509_check_email(3)>,
L<X509_check_ip(3)>,
L<openssl-x509(1)>
=head1 HISTORY
The B<X509_V_FLAG_NO_ALT_CHAINS> flag was added in OpenSSL 1.1.0.
The flag B<X509_V_FLAG_CB_ISSUER_CHECK> was deprecated in OpenSSL 1.1.0
and has no effect.
The X509_VERIFY_PARAM_get_hostflags() function was added in OpenSSL 1.1.0i.
The X509_VERIFY_PARAM_get0_host(), X509_VERIFY_PARAM_get0_email(),
and X509_VERIFY_PARAM_get1_ip_asc() functions were added in OpenSSL 3.0.
+The function X509_VERIFY_PARAM_add0_policy() was historically documented as
+enabling policy checking however the implementation has never done this.
+The documentation was changed to align with the implementation.
+
=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/doc/man5/config.pod b/doc/man5/config.pod
index 77a8055e81fa..a78ff4dc0657 100644
--- a/doc/man5/config.pod
+++ b/doc/man5/config.pod
@@ -1,585 +1,585 @@
=pod
=head1 NAME
config - OpenSSL CONF library configuration files
=head1 DESCRIPTION
This page documents the syntax of OpenSSL configuration files,
as parsed by L<NCONF_load(3)> and related functions.
This format is used by many of the OpenSSL commands, and to
initialize the libraries when used by any application.
The first part describes the general syntax of the configuration
files, and subsequent sections describe the semantics of individual
modules. Other modules are described in L<fips_config(5)> and
L<x509v3_config(5)>.
The syntax for defining ASN.1 values is described in
L<ASN1_generate_nconf(3)>.
=head1 SYNTAX
A configuration file is a series of lines. Blank lines, and whitespace
between the elements of a line, have no significance. A comment starts
with a B<#> character; the rest of the line is ignored. If the B<#>
is the first non-space character in a line, the entire line is ignored.
=head2 Directives
Two directives can be used to control the parsing of configuration files:
B<.include> and B<.pragma>.
For compatibility with older versions of OpenSSL, an equal sign after the
directive will be ignored. Older versions will treat it as an assignment,
so care should be taken if the difference in semantics is important.
A file can include other files using the include syntax:
.include [=] pathname
If B<pathname> is a simple filename, that file is included directly at
that point. Included files can have B<.include> statements that specify
other files. If B<pathname> is a directory, all files within that directory
that have a C<.cnf> or C<.conf> extension will be included. (This is only
available on systems with POSIX IO support.) Any sub-directories found
inside the B<pathname> are B<ignored>. Similarly, if a file is opened
while scanning a directory, and that file has an B<.include> directive
that specifies a directory, that is also ignored.
As a general rule, the B<pathname> should be an absolute path; this can
be enforced with the B<abspath> and B<includedir> pragmas, described below.
The environment variable B<OPENSSL_CONF_INCLUDE>, if it exists,
is prepended to all relative pathnames.
If the pathname is still relative, it is interpreted based on the
current working directory.
To require all file inclusions to name absolute paths, use the following
directive:
.pragma [=] abspath:value
The default behavior, where the B<value> is B<false> or B<off>, is to allow
relative paths. To require all B<.include> pathnames to be absolute paths,
use a B<value> of B<true> or B<on>.
In these files, the dollar sign, B<$>, is used to reference a variable, as
described below. On some platforms, however, it is common to treat B<$>
as a regular character in symbol names. Supporting this behavior can be
done with the following directive:
.pragma [=] dollarid:value
The default behavior, where the B<value> is B<false> or B<off>, is to treat
the dollarsign as indicating a variable name; C<foo$bar> is interpreted as
C<foo> followed by the expansion of the variable C<bar>. If B<value> is
-B<true> or B<on>, then C<foo$bar> is a single seven-character name nad
+B<true> or B<on>, then C<foo$bar> is a single seven-character name and
variable expansions must be specified using braces or parentheses.
.pragma [=] includedir:value
If a relative pathname is specified in the B<.include> directive, and
the B<OPENSSL_CONF_INCLUDE> environment variable doesn't exist, then
the value of the B<includedir> pragma, if it exists, is prepended to the
pathname.
=head2 Settings
A configuration file is divided into a number of I<sections>. A section
begins with the section name in square brackets, and ends when a new
section starts, or at the end of the file. The section name can consist
of alphanumeric characters and underscores.
Whitespace between the name and the brackets is removed.
The first section of a configuration file is special and is referred to
as the B<default> section. This section is usually unnamed and spans from
the start of file until the first named section. When a name is being
looked up, it is first looked up in the current or named section,
and then the default section if necessary.
The environment is mapped onto a section called B<ENV>.
Within a section are a series of name/value assignments, described in more
detail below. As a reminder, the square brackets shown in this example
are required, not optional:
[ section ]
name1 = This is value1
name2 = Another value
...
[ newsection ]
name1 = New value1
name3 = Value 3
The B<name> can contain any alphanumeric characters as well as a few
punctuation symbols such as B<.> B<,> B<;> and B<_>.
Whitespace after the name and before the equal sign is ignored.
If a name is repeated in the same section, then all but the last
value are ignored. In certain circumstances, such as with
Certificate DNs, the same field may occur multiple times.
In order to support this, commands like L<openssl-req(1)> ignore any
leading text that is preceded with a period. For example:
1.OU = First OU
2.OU = Second OU
The B<value> consists of the string following the B<=> character until end
of line with any leading and trailing whitespace removed.
The value string undergoes variable expansion. The text C<$var> or C<${var}>
inserts the value of the named variable from the current section.
To use a value from another section use C<$section::name>
or C<${section::name}>.
By using C<$ENV::name>, the value of the specified environment
variable will be substituted.
Variables must be defined before their value is referenced, otherwise
an error is flagged and the file will not load.
This can be worked around by specifying a default value in the B<default>
section before the variable is used.
Any name/value settings in an B<ENV> section are available
to the configuration file, but are not propagated to the environment.
It is an error if the value ends up longer than 64k.
It is possible to escape certain characters by using a single B<'> or
double B<"> quote around the value, or using a backslash B<\> before the
character,
By making the last character of a line a B<\>
a B<value> string can be spread across multiple lines. In addition
the sequences B<\n>, B<\r>, B<\b> and B<\t> are recognized.
The expansion and escape rules as described above that apply to B<value>
also apply to the pathname of the B<.include> directive.
=head1 OPENSSL LIBRARY CONFIGURATION
The sections below use the informal term I<module> to refer to a part
of the OpenSSL functionality. This is not the same as the formal term
I<FIPS module>, for example.
The OpenSSL configuration looks up the value of B<openssl_conf>
in the default section and takes that as the name of a section that specifies
how to configure any modules in the library. It is not an error to leave
any module in its default configuration. An application can specify a
different name by calling CONF_modules_load_file(), for example, directly.
OpenSSL also looks up the value of B<config_diagnostics>.
If this exists and has a nonzero numeric value, any error suppressing flags
passed to CONF_modules_load() will be ignored.
This is useful for diagnosing misconfigurations but its use in
production requires additional consideration. With this option enabled,
a configuration error will completely prevent access to a service.
Without this option and in the presence of a configuration error, access
will be allowed but the desired configuration will B<not> be used.
# These must be in the default section
config_diagnostics = 1
openssl_conf = openssl_init
[openssl_init]
oid_section = oids
providers = providers
alg_section = evp_properties
ssl_conf = ssl_configuration
engines = engines
random = random
[oids]
... new oids here ...
[providers]
... provider stuff here ...
[evp_properties]
... EVP properties here ...
[ssl_configuration]
... SSL/TLS configuration properties here ...
[engines]
... engine properties here ...
[random]
... random properties here ...
The semantics of each module are described below. The phrase "in the
initialization section" refers to the section identified by the
B<openssl_conf> or other name (given as B<openssl_init> in the
example above). The examples below assume the configuration above
is used to specify the individual sections.
=head2 ASN.1 Object Identifier Configuration
The name B<oid_section> in the initialization section names the section
containing name/value pairs of OID's.
The name is the short name; the value is an optional long name followed
by a comma, and the numeric value.
While some OpenSSL commands have their own section for specifying OID's,
this section makes them available to all commands and applications.
[oids]
shortName = a very long OID name, 1.2.3.4
newoid1 = 1.2.3.4.1
some_other_oid = 1.2.3.5
If a full configuration with the above fragment is in the file
F<example.cnf>, then the following command line:
OPENSSL_CONF=example.cnf openssl asn1parse -genstr OID:1.2.3.4.1
will output:
0:d=0 hl=2 l= 4 prim: OBJECT :newoid1
showing that the OID "newoid1" has been added as "1.2.3.4.1".
=head2 Provider Configuration
The name B<providers> in the initialization section names the section
containing cryptographic provider configuration. The name/value assignments
in this section each name a provider, and point to the configuration section
for that provider. The provider-specific section is used to specify how
to load the module, activate it, and set other parameters.
Within a provider section, the following names have meaning:
=over 4
=item B<identity>
This is used to specify an alternate name, overriding the default name
specified in the list of providers. For example:
[providers]
foo = foo_provider
[foo_provider]
identity = my_fips_module
=item B<module>
Specifies the pathname of the module (typically a shared library) to load.
=item B<activate>
If present, the module is activated. The value assigned to this name is not
significant.
=back
All parameters in the section as well as sub-sections are made
available to the provider.
=head3 Default provider and its activation
If no providers are activated explicitly, the default one is activated implicitly.
See L<OSSL_PROVIDER-default(7)> for more details.
If you add a section explicitly activating any other provider(s),
you most probably need to explicitly activate the default provider,
otherwise it becomes unavailable in openssl. It may make the system remotely unavailable.
=head2 EVP Configuration
The name B<alg_section> in the initialization section names the section
containing algorithmic properties when using the B<EVP> API.
Within the algorithm properties section, the following names have meaning:
=over 4
=item B<default_properties>
The value may be anything that is acceptable as a property query
string for EVP_set_default_properties().
=item B<fips_mode> (deprecated)
The value is a boolean that can be B<yes> or B<no>. If the value is
B<yes>, this is exactly equivalent to:
default_properties = fips=yes
If the value is B<no>, nothing happens. Using this name is deprecated, and
if used, it must be the only name in the section.
=back
=head2 SSL Configuration
The name B<ssl_conf> in the initialization section names the section
containing the list of SSL/TLS configurations.
As with the providers, each name in this section identifies a
section with the configuration for that name. For example:
[ssl_configuration]
server = server_tls_config
client = client_tls_config
system_default = tls_system_default
[server_tls_config]
... configuration for SSL/TLS servers ...
[client_tls_config]
... configuration for SSL/TLS clients ...
The configuration name B<system_default> has a special meaning. If it
exists, it is applied whenever an B<SSL_CTX> object is created. For example,
to impose system-wide minimum TLS and DTLS protocol versions:
[tls_system_default]
MinProtocol = TLSv1.2
MinProtocol = DTLSv1.2
The minimum TLS protocol is applied to B<SSL_CTX> objects that are TLS-based,
and the minimum DTLS protocol to those are DTLS-based.
The same applies also to maximum versions set with B<MaxProtocol>.
Each configuration section consists of name/value pairs that are parsed
by B<SSL_CONF_cmd(3)>, which will be called by SSL_CTX_config() or
SSL_config(), appropriately. Note that any characters before an initial
dot in the configuration section are ignored, so that the same command can
be used multiple times. This probably is most useful for loading different
key types, as shown here:
[server_tls_config]
RSA.Certificate = server-rsa.pem
ECDSA.Certificate = server-ecdsa.pem
=head2 Engine Configuration
The name B<engines> in the initialization section names the section
containing the list of ENGINE configurations.
As with the providers, each name in this section identifies an engine
with the configuration for that engine.
The engine-specific section is used to specify how to load the engine,
activate it, and set other parameters.
Within an engine section, the following names have meaning:
=over 4
=item B<engine_id>
This is used to specify an alternate name, overriding the default name
specified in the list of engines. If present, it must be first.
For example:
[engines]
foo = foo_engine
[foo_engine]
engine_id = myfoo
=item B<dynamic_path>
This loads and adds an ENGINE from the given path. It is equivalent to
sending the ctrls B<SO_PATH> with the path argument followed by B<LIST_ADD>
with value B<2> and B<LOAD> to the dynamic ENGINE. If this is not the
required behaviour then alternative ctrls can be sent directly to the
dynamic ENGINE using ctrl commands.
=item B<init>
This specifies whether to initialize the ENGINE. If the value is B<0> the
ENGINE will not be initialized, if the value is B<1> an attempt is made
to initialize
the ENGINE immediately. If the B<init> command is not present then an
attempt will be made to initialize the ENGINE after all commands in its
section have been processed.
=item B<default_algorithms>
This sets the default algorithms an ENGINE will supply using the function
ENGINE_set_default_string().
=back
All other names are taken to be the name of a ctrl command that is
sent to the ENGINE, and the value is the argument passed with the command.
The special value B<EMPTY> means no value is sent with the command.
For example:
[engines]
foo = foo_engine
[foo_engine]
dynamic_path = /some/path/fooengine.so
some_ctrl = some_value
default_algorithms = ALL
other_ctrl = EMPTY
=head2 Random Configuration
The name B<random> in the initialization section names the section
containing the random number generater settings.
Within the random section, the following names have meaning:
=over 4
=item B<random>
This is used to specify the random bit generator.
For example:
[random]
random = CTR-DRBG
The available random bit generators are:
=over 4
=item B<CTR-DRBG>
=item B<HASH-DRBG>
=item B<HMAC-DRBG>
=back
=item B<cipher>
This specifies what cipher a B<CTR-DRBG> random bit generator will use.
Other random bit generators ignore this name.
The default value is B<AES-256-CTR>.
=item B<digest>
This specifies what digest the B<HASH-DRBG> or B<HMAC-DRBG> random bit
generators will use. Other random bit generators ignore this name.
=item B<properties>
This sets the property query used when fetching the random bit generator and
any underlying algorithms.
=item B<seed>
This sets the randomness source that should be used. By default B<SEED-SRC>
will be used outside of the FIPS provider. The FIPS provider uses call backs
to access the same randomness sources from outside the validated boundary.
=item B<seed_properties>
This sets the property query used when fetching the randomness source.
=back
=head1 EXAMPLES
This example shows how to use quoting and escaping.
# This is the default section.
HOME = /temp
configdir = $ENV::HOME/config
[ section_one ]
# Quotes permit leading and trailing whitespace
any = " any variable name "
other = A string that can \
cover several lines \
by including \\ characters
message = Hello World\n
[ section_two ]
greeting = $section_one::message
This example shows how to expand environment variables safely.
In this example, the variable B<tempfile> is intended to refer
to a temporary file, and the environment variable B<TEMP> or
B<TMP>, if present, specify the directory where the file
should be put.
Since the default section is checked if a variable does not
exist, it is possible to set B<TMP> to default to F</tmp>, and
B<TEMP> to default to B<TMP>.
# These two lines must be in the default section.
TMP = /tmp
TEMP = $ENV::TMP
# This can be used anywhere
tmpfile = ${ENV::TEMP}/tmp.filename
This example shows how to enforce FIPS mode for the application
F<sample>.
sample = fips_config
[fips_config]
alg_section = evp_properties
[evp_properties]
default_properties = "fips=yes"
=head1 ENVIRONMENT
=over 4
=item B<OPENSSL_CONF>
The path to the config file, or the empty string for none.
Ignored in set-user-ID and set-group-ID programs.
=item B<OPENSSL_ENGINES>
The path to the engines directory.
Ignored in set-user-ID and set-group-ID programs.
=item B<OPENSSL_MODULES>
The path to the directory with OpenSSL modules, such as providers.
Ignored in set-user-ID and set-group-ID programs.
=item B<OPENSSL_CONF_INCLUDE>
The optional path to prepend to all B<.include> paths.
=back
=head1 BUGS
There is no way to include characters using the octal B<\nnn> form. Strings
are all null terminated so nulls cannot form part of the value.
The escaping isn't quite right: if you want to use sequences like B<\n>
you can't use any quote escaping on the same line.
The limit that only one directory can be opened and read at a time
can be considered a bug and should be fixed.
=head1 HISTORY
An undocumented API, NCONF_WIN32(), used a slightly different set
of parsing rules there were intended to be tailored to
the Microsoft Windows platform.
Specifically, the backslash character was not an escape character and
could be used in pathnames, only the double-quote character was recognized,
and comments began with a semi-colon.
This function was deprecated in OpenSSL 3.0; applications with
configuration files using that syntax will have to be modified.
=head1 SEE ALSO
L<openssl-x509(1)>, L<openssl-req(1)>, L<openssl-ca(1)>,
L<openssl-fipsinstall(1)>,
L<ASN1_generate_nconf(3)>,
L<EVP_set_default_properties(3)>,
L<CONF_modules_load(3)>,
L<CONF_modules_load_file(3)>,
L<fips_config(5)>, and
L<x509v3_config(5)>.
=head1 COPYRIGHT
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man7/EVP_CIPHER-NULL.pod b/doc/man7/EVP_CIPHER-NULL.pod
new file mode 100644
index 000000000000..44e07dcf1b05
--- /dev/null
+++ b/doc/man7/EVP_CIPHER-NULL.pod
@@ -0,0 +1,72 @@
+=pod
+
+=head1 NAME
+
+EVP_CIPHER-NULL - The NULL EVP_CIPHER implementation
+
+=head1 DESCRIPTION
+
+Support for a NULL symmetric encryption using the B<EVP_CIPHER> API.
+This is used when the TLS cipher suite is TLS_NULL_WITH_NULL_NULL.
+This does no encryption (just copies the data) and has a mac size of zero.
+
+=head2 Algorithm Name
+
+The following algorithm is available in the default provider:
+
+=over 4
+
+=item "NULL"
+
+=back
+
+=head2 Parameters
+
+This implementation supports the following parameters:
+
+=head3 Gettable EVP_CIPHER parameters
+
+See L<EVP_EncryptInit(3)/Gettable EVP_CIPHER parameters>
+
+=head3 Gettable EVP_CIPHER_CTX parameters
+
+=over 4
+
+=item "keylen" (B<OSSL_CIPHER_PARAM_KEYLEN>) <unsigned integer>
+
+=item "ivlen" (B<OSSL_CIPHER_PARAM_IVLEN> and <B<OSSL_CIPHER_PARAM_AEAD_IVLEN>) <unsigned integer>
+
+=item "tls-mac" (B<OSSL_CIPHER_PARAM_TLS_MAC>) <octet ptr>
+
+=back
+
+See L<EVP_EncryptInit(3)/PARAMETERS> for further information.
+
+=head3 Settable EVP_CIPHER_CTX parameters
+
+=over 4
+
+=item "tls-mac-size" (B<OSSL_CIPHER_PARAM_TLS_MAC_SIZE>) <unsigned integer>
+
+=back
+
+See L<EVP_EncryptInit(3)/PARAMETERS> for further information.
+
+=head1 CONFORMING TO
+
+RFC 5246 section-6.2.3.1
+
+=head1 SEE ALSO
+
+L<provider-cipher(7)>, L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 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/doc/man7/EVP_MD-NULL.pod b/doc/man7/EVP_MD-NULL.pod
new file mode 100644
index 000000000000..bce399a1e121
--- /dev/null
+++ b/doc/man7/EVP_MD-NULL.pod
@@ -0,0 +1,42 @@
+=pod
+
+=head1 NAME
+
+EVP_MD-NULL - The NULL EVP_MD implementation
+
+=head1 DESCRIPTION
+
+Support for a NULL digest through the B<EVP_MD> API.
+This algorithm does nothing and returns 1 for its init,
+update and final methods.
+
+=head2 Algorithm Name
+
+The following algorithm is available in the default provider:
+
+=over 4
+
+=item "NULL"
+
+=back
+
+=head2 Gettable Parameters
+
+This implementation supports the common gettable parameters described
+in L<EVP_MD-common(7)>.
+
+=head1 SEE ALSO
+
+L<EVP_MD_CTX_set_params(3)>, L<provider-digest(7)>,
+L<OSSL_PROVIDER-default(7)>
+
+=head1 COPYRIGHT
+
+Copyright 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/doc/man7/EVP_PKEY-EC.pod b/doc/man7/EVP_PKEY-EC.pod
index 668a024014b4..4b6dec35862c 100644
--- a/doc/man7/EVP_PKEY-EC.pod
+++ b/doc/man7/EVP_PKEY-EC.pod
@@ -1,282 +1,282 @@
=pod
=head1 NAME
EVP_PKEY-EC,
EVP_KEYMGMT-EC
- EVP_PKEY EC keytype and algorithm support
=head1 DESCRIPTION
The B<EC> keytype is implemented in OpenSSL's default provider.
=head2 Common EC parameters
The normal way of specifying domain parameters for an EC curve is via the
curve name "group". For curves with no curve name, explicit parameters can be
used that specify "field-type", "p", "a", "b", "generator" and "order".
Explicit parameters are supported for backwards compability reasons, but they
are not compliant with multiple standards (including RFC5915) which only allow
named curves.
The following KeyGen/Gettable/Import/Export types are available for the
built-in EC algorithm:
=over 4
=item "group" (B<OSSL_PKEY_PARAM_GROUP_NAME>) <UTF8 string>
The curve name.
=item "field-type" (B<OSSL_PKEY_PARAM_EC_FIELD_TYPE>) <UTF8 string>
The value should be either "prime-field" or "characteristic-two-field",
which correspond to prime field Fp and binary field F2^m.
=item "p" (B<OSSL_PKEY_PARAM_EC_P>) <unsigned integer>
For a curve over Fp I<p> is the prime for the field. For a curve over F2^m I<p>
represents the irreducible polynomial - each bit represents a term in the
polynomial. Therefore, there will either be three or five bits set dependent on
whether the polynomial is a trinomial or a pentanomial.
=item "a" (B<OSSL_PKEY_PARAM_EC_A>) <unsigned integer>
=item "b" (B<OSSL_PKEY_PARAM_EC_B>) <unsigned integer>
=item "seed" (B<OSSL_PKEY_PARAM_EC_SEED>) <octet string>
I<a> and I<b> represents the coefficients of the curve
For Fp: y^2 mod p = x^3 +ax + b mod p OR
For F2^m: y^2 + xy = x^3 + ax^2 + b
I<seed> is an optional value that is for information purposes only.
It represents the random number seed used to generate the coefficient I<b> from a
random number.
=item "generator" (B<OSSL_PKEY_PARAM_EC_GENERATOR>) <octet string>
=item "order" (B<OSSL_PKEY_PARAM_EC_ORDER>) <unsigned integer>
=item "cofactor" (B<OSSL_PKEY_PARAM_EC_COFACTOR>) <unsigned integer>
The I<generator> is a well defined point on the curve chosen for cryptographic
operations. The encoding conforms with Sec. 2.3.3 of the SECG SEC 1 ("Elliptic Curve
Cryptography") standard. See EC_POINT_oct2point().
Integers used for point multiplications will be between 0 and
I<order> - 1.
I<cofactor> is an optional value.
I<order> multiplied by the I<cofactor> gives the number of points on the curve.
=item "decoded-from-explicit" (B<OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS>) <integer>
Gets a flag indicating wether the key or parameters were decoded from explicit
curve parameters. Set to 1 if so or 0 if a named curve was used.
=item "use-cofactor-flag" (B<OSSL_PKEY_PARAM_USE_COFACTOR_ECDH>) <integer>
Enable Cofactor DH (ECC CDH) if this value is 1, otherwise it uses normal EC DH
if the value is zero. The cofactor variant multiplies the shared secret by the
EC curve's cofactor (note for some curves the cofactor is 1).
See also L<EVP_KEYEXCH-ECDH(7)> for the related
B<OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE> parameter that can be set on a
per-operation basis.
=item "encoding" (B<OSSL_PKEY_PARAM_EC_ENCODING>) <UTF8 string>
Set the format used for serializing the EC group parameters.
Valid values are "explicit" or "named_curve". The default value is "named_curve".
=item "point-format" (B<OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT>) <UTF8 string>
Sets or gets the point_conversion_form for the I<key>. For a description of
point_conversion_forms please see L<EC_POINT_new(3)>. Valid values are
"uncompressed" or "compressed". The default value is "uncompressed".
=item "group-check" (B<OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE>) <UTF8 string>
Sets or Gets the type of group check done when EVP_PKEY_param_check() is called.
Valid values are "default", "named" and "named-nist".
The "named" type checks that the domain parameters match the inbuilt curve parameters,
"named-nist" is similiar but also checks that the named curve is a nist curve.
The "default" type does domain parameter validation for the OpenSSL default provider,
but is equivalent to "named-nist" for the OpenSSL FIPS provider.
=item "include-public" (B<OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC>) <integer>
Setting this value to 0 indicates that the public key should not be included when
encoding the private key. The default value of 1 will include the public key.
=item "pub" (B<OSSL_PKEY_PARAM_PUB_KEY>) <octet string>
The public key value in encoded EC point format conforming to Sec. 2.3.3 and
2.3.4 of the SECG SEC 1 ("Elliptic Curve Cryptography") standard.
This parameter is used when importing or exporting the public key value with the
EVP_PKEY_fromdata() and EVP_PKEY_todata() functions.
Note, in particular, that the choice of point compression format used for
encoding the exported value via EVP_PKEY_todata() depends on the underlying
provider implementation.
Before OpenSSL 3.0.8, the implementation of providers included with OpenSSL always
opted for an encoding in compressed format, unconditionally.
Since OpenSSL 3.0.8, the implementation has been changed to honor the
B<OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT> parameter, if set, or to default
to uncompressed format.
=item "priv" (B<OSSL_PKEY_PARAM_PRIV_KEY>) <unsigned integer>
The private key value.
=item "encoded-pub-key" (B<OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY>) <octet string>
Used for getting and setting the encoding of an EC public key. The public key
is expected to be a point conforming to Sec. 2.3.4 of the SECG SEC 1 ("Elliptic
Curve Cryptography") standard.
=item "qx" (B<OSSL_PKEY_PARAM_EC_PUB_X>) <unsigned integer>
Used for getting the EC public key X component.
=item "qy" (B<OSSL_PKEY_PARAM_EC_PUB_Y>) <unsigned integer>
Used for getting the EC public key Y component.
-=item (B<OSSL_PKEY_PARAM_DEFAULT_DIGEST>) <UTF8 string>
+=item "default-digest" (B<OSSL_PKEY_PARAM_DEFAULT_DIGEST>) <UTF8 string>
Getter that returns the default digest name.
(Currently returns "SHA256" as of OpenSSL 3.0).
=back
The following Gettable types are also available for the built-in EC algorithm:
=over 4
=item "basis-type" (B<OSSL_PKEY_PARAM_EC_CHAR2_TYPE>) <UTF8 string>
Supports the values "tpBasis" for a trinomial or "ppBasis" for a pentanomial.
This field is only used for a binary field F2^m.
=item "m" (B<OSSL_PKEY_PARAM_EC_CHAR2_M>) <integer>
=item "tp" (B<OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS>) <integer>
=item "k1" (B<OSSL_PKEY_PARAM_EC_CHAR2_PP_K1>) <integer>
=item "k2" (B<OSSL_PKEY_PARAM_EC_CHAR2_PP_K2>) <integer>
=item "k3" (B<OSSL_PKEY_PARAM_EC_CHAR2_PP_K3>) <integer>
These fields are only used for a binary field F2^m.
I<m> is the degree of the binary field.
I<tp> is the middle bit of a trinomial so its value must be in the
range m > tp > 0.
I<k1>, I<k2> and I<k3> are used to get the middle bits of a pentanomial such
that m > k3 > k2 > k1 > 0
=back
=head2 EC key validation
For EC keys, L<EVP_PKEY_param_check(3)> behaves in the following way:
For the OpenSSL default provider it uses either
L<EC_GROUP_check(3)> or L<EC_GROUP_check_named_curve(3)> depending on the flag
EC_FLAG_CHECK_NAMED_GROUP.
The OpenSSL FIPS provider uses L<EC_GROUP_check_named_curve(3)> in order to
conform to SP800-56Ar3 I<Assurances of Domain-Parameter Validity>.
For EC keys, L<EVP_PKEY_param_check_quick(3)> is equivalent to
L<EVP_PKEY_param_check(3)>.
For EC keys, L<EVP_PKEY_public_check(3)> and L<EVP_PKEY_public_check_quick(3)>
conform to SP800-56Ar3 I<ECC Full Public-Key Validation> and
I<ECC Partial Public-Key Validation> respectively.
For EC Keys, L<EVP_PKEY_private_check(3)> and L<EVP_PKEY_pairwise_check(3)>
conform to SP800-56Ar3 I<Private key validity> and
I<Owner Assurance of Pair-wise Consistency> respectively.
=head1 EXAMPLES
An B<EVP_PKEY> context can be obtained by calling:
EVP_PKEY_CTX *pctx =
EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
An B<EVP_PKEY> ECDSA or ECDH key can be generated with a "P-256" named group by
calling:
pkey = EVP_EC_gen("P-256");
or like this:
EVP_PKEY *key = NULL;
OSSL_PARAM params[2];
EVP_PKEY_CTX *gctx =
EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
EVP_PKEY_keygen_init(gctx);
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
"P-256", 0);
params[1] = OSSL_PARAM_construct_end();
EVP_PKEY_CTX_set_params(gctx, params);
EVP_PKEY_generate(gctx, &key);
EVP_PKEY_print_private(bio_out, key, 0, NULL);
...
EVP_PKEY_free(key);
EVP_PKEY_CTX_free(gctx);
An B<EVP_PKEY> EC CDH (Cofactor Diffie-Hellman) key can be generated with a
"K-571" named group by calling:
int use_cdh = 1;
EVP_PKEY *key = NULL;
OSSL_PARAM params[3];
EVP_PKEY_CTX *gctx =
EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
EVP_PKEY_keygen_init(gctx);
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
"K-571", 0);
/*
* This curve has a cofactor that is not 1 - so setting CDH mode changes
* the behaviour. For many curves the cofactor is 1 - so setting this has
* no effect.
*/
params[1] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
&use_cdh);
params[2] = OSSL_PARAM_construct_end();
EVP_PKEY_CTX_set_params(gctx, params);
EVP_PKEY_generate(gctx, &key);
EVP_PKEY_print_private(bio_out, key, 0, NULL);
...
EVP_PKEY_free(key);
EVP_PKEY_CTX_free(gctx);
=head1 SEE ALSO
L<EVP_EC_gen(3)>,
L<EVP_KEYMGMT(3)>,
L<EVP_PKEY(3)>,
L<provider-keymgmt(7)>,
L<EVP_SIGNATURE-ECDSA(7)>,
L<EVP_KEYEXCH-ECDH(7)>
=head1 COPYRIGHT
-Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man7/OSSL_PROVIDER-FIPS.pod b/doc/man7/OSSL_PROVIDER-FIPS.pod
index 58008ae59f19..2f34866d998b 100644
--- a/doc/man7/OSSL_PROVIDER-FIPS.pod
+++ b/doc/man7/OSSL_PROVIDER-FIPS.pod
@@ -1,419 +1,435 @@
=pod
=head1 NAME
OSSL_PROVIDER-FIPS - OpenSSL FIPS provider
=head1 DESCRIPTION
The OpenSSL FIPS provider is a special provider that conforms to the Federal
Information Processing Standards (FIPS) specified in FIPS 140-2. This 'module'
contains an approved set of cryptographic algorithms that is validated by an
accredited testing laboratory.
=head2 Properties
The implementations in this provider specifically have these properties
defined:
=over 4
=item "provider=fips"
=item "fips=yes"
=back
It may be used in a property query string with fetching functions such as
L<EVP_MD_fetch(3)> or L<EVP_CIPHER_fetch(3)>, as well as with other
functions that take a property query string, such as
L<EVP_PKEY_CTX_new_from_name(3)>.
It isn't mandatory to query for any of these properties, except to
make sure to get implementations of this provider and none other.
The "fips=yes" property can be use to make sure only FIPS approved
implementations are used for crypto operations. This may also include
other non-crypto support operations that are not in the FIPS provider,
such as asymmetric key encoders,
see L<OSSL_PROVIDER-default(7)/Asymmetric Key Management>.
=head1 OPERATIONS AND ALGORITHMS
The OpenSSL FIPS provider supports these operations and algorithms:
=head2 Hashing Algorithms / Message Digests
=over 4
=item SHA1, see L<EVP_MD-SHA1(7)>
=item SHA2, see L<EVP_MD-SHA2(7)>
=item SHA3, see L<EVP_MD-SHA3(7)>
=item KECCAK-KMAC, see L<EVP_MD-KECCAK-KMAC(7)>
=back
=head2 Symmetric Ciphers
=over 4
=item AES, see L<EVP_CIPHER-AES(7)>
=item DES-EDE3 (TripleDES), see L<EVP_CIPHER-DES(7)>
=back
=head2 Message Authentication Code (MAC)
=over 4
=item CMAC, see L<EVP_MAC-CMAC(7)>
=item GMAC, see L<EVP_MAC-GMAC(7)>
=item HMAC, see L<EVP_MAC-HMAC(7)>
=item KMAC, see L<EVP_MAC-KMAC(7)>
=back
=head2 Key Derivation Function (KDF)
=over 4
=item HKDF, see L<EVP_KDF-HKDF(7)>
=item TLS13-KDF, see L<EVP_KDF-TLS13_KDF(7)>
=item SSKDF, see L<EVP_KDF-SS(7)>
=item PBKDF2, see L<EVP_KDF-PBKDF2(7)>
=item SSHKDF, see L<EVP_KDF-SSHKDF(7)>
=item TLS1-PRF, see L<EVP_KDF-TLS1_PRF(7)>
=item KBKDF, see L<EVP_KDF-KB(7)>
=item X942KDF-ASN1, see L<EVP_KDF-X942-ASN1(7)>
=item X942KDF-CONCAT, see L<EVP_KDF-X942-CONCAT(7)>
=item X963KDF, see L<EVP_KDF-X963(7)>
=back
=head2 Key Exchange
=over 4
=item DH, see L<EVP_KEYEXCH-DH(7)>
=item ECDH, see L<EVP_KEYEXCH-ECDH(7)>
=item X25519, see L<EVP_KEYEXCH-X25519(7)>
=item X448, see L<EVP_KEYEXCH-X448(7)>
=back
=head2 Asymmetric Signature
=over 4
=item RSA, see L<EVP_SIGNATURE-RSA(7)>
=item X25519, see L<EVP_SIGNATURE-ED25519(7)>
=item X448, see L<EVP_SIGNATURE-ED448(7)>
=item HMAC, see L<EVP_SIGNATURE-HMAC(7)>
=item CMAC, see L<EVP_SIGNATURE-CMAC(7)>
=back
=head2 Asymmetric Cipher
=over 4
=item RSA, see L<EVP_ASYM_CIPHER-RSA(7)>
=back
=head2 Asymmetric Key Encapsulation
=over 4
=item RSA, see L<EVP_KEM-RSA(7)>
=back
=head2 Asymmetric Key Management
=over 4
=item DH, see L<EVP_KEYMGMT-DH(7)>
=item DHX, see L<EVP_KEYMGMT-DHX(7)>
=item DSA, see L<EVP_KEYMGMT-DSA(7)>
=item RSA, see L<EVP_KEYMGMT-RSA(7)>
=item EC, see L<EVP_KEYMGMT-EC(7)>
=item X25519, see L<EVP_KEYMGMT-X25519(7)>
=item X448, see L<EVP_KEYMGMT-X448(7)>
=back
+=head2 Random Number Generation
+
+=over 4
+
+=item CTR-DRBG, see L<EVP_RAND-CTR-DRBG(7)>
+
+=item HASH-DRBG, see L<EVP_RAND-HASH-DRBG(7)>
+
+=item HMAC-DRBG, see L<EVP_RAND-HMAC-DRBG(7)>
+
+=item TEST-RAND, see L<EVP_RAND-TEST-RAND(7)>
+
+TEST-RAND is an unapproved algorithm.
+
+=back
+
=head1 SELF TESTING
One of the requirements for the FIPS module is self testing. An optional callback
mechanism is available to return information to the user using
L<OSSL_SELF_TEST_set_callback(3)>.
The parameters passed to the callback are described in L<OSSL_SELF_TEST_new(3)>
The OpenSSL FIPS module uses the following mechanism to provide information
about the self tests as they run.
This is useful for debugging if a self test is failing.
The callback also allows forcing any self test to fail, in order to check that
it operates correctly on failure.
Note that all self tests run even if a self test failure occurs.
The FIPS module passes the following type(s) to OSSL_SELF_TEST_onbegin().
=over 4
=item "Module_Integrity" (B<OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY>)
Uses HMAC SHA256 on the module file to validate that the module has not been
modified. The integrity value is compared to a value written to a configuration
file during installation.
=item "Install_Integrity" (B<OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY>)
Uses HMAC SHA256 on a fixed string to validate that the installation process
has already been performed and the self test KATS have already been tested,
The integrity value is compared to a value written to a configuration
file after successfully running the self tests during installation.
=item "KAT_Cipher" (B<OSSL_SELF_TEST_TYPE_KAT_CIPHER>)
Known answer test for a symmetric cipher.
=item "KAT_AsymmetricCipher" (B<OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER>)
Known answer test for a asymmetric cipher.
=item "KAT_Digest" (B<OSSL_SELF_TEST_TYPE_KAT_DIGEST>)
Known answer test for a digest.
=item "KAT_Signature" (B<OSSL_SELF_TEST_TYPE_KAT_SIGNATURE>)
Known answer test for a signature.
=item "PCT_Signature" (B<OSSL_SELF_TEST_TYPE_PCT_SIGNATURE>)
Pairwise Consistency check for a signature.
=item "KAT_KDF" (B<OSSL_SELF_TEST_TYPE_KAT_KDF>)
Known answer test for a key derivation function.
=item "KAT_KA" (B<OSSL_SELF_TEST_TYPE_KAT_KA>)
Known answer test for key agreement.
=item "DRBG" (B<OSSL_SELF_TEST_TYPE_DRBG>)
Known answer test for a Deterministic Random Bit Generator.
=item "Conditional_PCT" (B<OSSL_SELF_TEST_TYPE_PCT>)
Conditional test that is run during the generation of key pairs.
=item "Continuous_RNG_Test" (B<OSSL_SELF_TEST_TYPE_CRNG>)
Continuous random number generator test.
=back
The "Module_Integrity" self test is always run at startup.
The "Install_Integrity" self test is used to check if the self tests have
already been run at installation time. If they have already run then the
self tests are not run on subsequent startups.
All other self test categories are run once at installation time, except for the
"Pairwise_Consistency_Test".
There is only one instance of the "Module_Integrity" and "Install_Integrity"
self tests. All other self tests may have multiple instances.
The FIPS module passes the following descriptions(s) to OSSL_SELF_TEST_onbegin().
=over 4
=item "HMAC" (B<OSSL_SELF_TEST_DESC_INTEGRITY_HMAC>)
"Module_Integrity" and "Install_Integrity" use this.
=item "RSA" (B<OSSL_SELF_TEST_DESC_PCT_RSA_PKCS1>)
=item "ECDSA" (B<OSSL_SELF_TEST_DESC_PCT_ECDSA>)
=item "DSA" (B<OSSL_SELF_TEST_DESC_PCT_DSA>)
Key generation tests used with the "Pairwise_Consistency_Test" type.
=item "RSA_Encrypt" (B<OSSL_SELF_TEST_DESC_ASYM_RSA_ENC>)
=item "RSA_Decrypt" (B<OSSL_SELF_TEST_DESC_ASYM_RSA_DEC>)
"KAT_AsymmetricCipher" uses this to indicate an encrypt or decrypt KAT.
=item "AES_GCM" (B<OSSL_SELF_TEST_DESC_CIPHER_AES_GCM>)
=item "AES_ECB_Decrypt" (B<OSSL_SELF_TEST_DESC_CIPHER_AES_ECB>)
=item "TDES" (B<OSSL_SELF_TEST_DESC_CIPHER_TDES>)
Symmetric cipher tests used with the "KAT_Cipher" type.
=item "SHA1" (B<OSSL_SELF_TEST_DESC_MD_SHA1>)
=item "SHA2" (B<OSSL_SELF_TEST_DESC_MD_SHA2>)
=item "SHA3" (B<OSSL_SELF_TEST_DESC_MD_SHA3>)
Digest tests used with the "KAT_Digest" type.
=item "DSA" (B<OSSL_SELF_TEST_DESC_SIGN_DSA>)
=item "RSA" (B<OSSL_SELF_TEST_DESC_SIGN_RSA>)
=item "ECDSA" (B<OSSL_SELF_TEST_DESC_SIGN_ECDSA>)
Signature tests used with the "KAT_Signature" type.
=item "ECDH" (B<OSSL_SELF_TEST_DESC_KA_ECDH>)
=item "DH" (B<OSSL_SELF_TEST_DESC_KA_DH>)
Key agreement tests used with the "KAT_KA" type.
=item "HKDF" (B<OSSL_SELF_TEST_DESC_KDF_HKDF>)
=item "TLS13_KDF_EXTRACT" (B<OSSL_SELF_TEST_DESC_KDF_TLS13_EXTRACT>)
=item "TLS13_KDF_EXPAND" (B<OSSL_SELF_TEST_DESC_KDF_TLS13_EXPAND>)
=item "SSKDF" (B<OSSL_SELF_TEST_DESC_KDF_SSKDF>)
=item "X963KDF" (B<OSSL_SELF_TEST_DESC_KDF_X963KDF>)
=item "X942KDF" (B<OSSL_SELF_TEST_DESC_KDF_X942KDF>)
=item "PBKDF2" (B<OSSL_SELF_TEST_DESC_KDF_PBKDF2>)
=item "SSHKDF" (B<OSSL_SELF_TEST_DESC_KDF_SSHKDF>)
=item "TLS12_PRF" (B<OSSL_SELF_TEST_DESC_KDF_TLS12_PRF>)
=item "KBKDF" (B<OSSL_SELF_TEST_DESC_KDF_KBKDF>)
Key Derivation Function tests used with the "KAT_KDF" type.
=item "CTR" (B<OSSL_SELF_TEST_DESC_DRBG_CTR>)
=item "HASH" (B<OSSL_SELF_TEST_DESC_DRBG_HASH>)
=item "HMAC" (B<OSSL_SELF_TEST_DESC_DRBG_HMAC>)
DRBG tests used with the "DRBG" type.
= item "RNG" (B<OSSL_SELF_TEST_DESC_RNG>)
"Continuous_RNG_Test" uses this.
=back
=head1 EXAMPLES
A simple self test callback is shown below for illustrative purposes.
#include <openssl/self_test.h>
static OSSL_CALLBACK self_test_cb;
static int self_test_cb(const OSSL_PARAM params[], void *arg)
{
int ret = 0;
const OSSL_PARAM *p = NULL;
const char *phase = NULL, *type = NULL, *desc = NULL;
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;
/* Do some logging */
if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0)
BIO_printf(bio_out, "%s : (%s) : ", desc, type);
if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0
|| strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0)
BIO_printf(bio_out, "%s\n", phase);
/* Corrupt the SHA1 self test during the 'corrupt' phase by returning 0 */
if (strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 0
&& strcmp(desc, OSSL_SELF_TEST_DESC_MD_SHA1) == 0) {
BIO_printf(bio_out, "%s %s", phase, desc);
return 0;
}
ret = 1;
err:
return ret;
}
=head1 SEE ALSO
L<openssl-fipsinstall(1)>,
L<fips_config(5)>,
L<OSSL_SELF_TEST_set_callback(3)>,
L<OSSL_SELF_TEST_new(3)>,
L<OSSL_PARAM(3)>,
L<openssl-core.h(7)>,
L<openssl-core_dispatch.h(7)>,
L<provider(7)>
=head1 HISTORY
This functionality was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man7/OSSL_PROVIDER-default.pod b/doc/man7/OSSL_PROVIDER-default.pod
index 43ba0ef02d52..e39d76abdbb8 100644
--- a/doc/man7/OSSL_PROVIDER-default.pod
+++ b/doc/man7/OSSL_PROVIDER-default.pod
@@ -1,261 +1,281 @@
=pod
=head1 NAME
OSSL_PROVIDER-default - OpenSSL default provider
=head1 DESCRIPTION
The OpenSSL default provider supplies the majority of OpenSSL's diverse
algorithm implementations. If an application doesn't specify anything else
explicitly (e.g. in the application or via config), then this is the
provider that will be used as fallback: It is loaded automatically the
first time that an algorithm is fetched from a provider or a function
acting on providers is called and no other provider has been loaded yet.
If an attempt to load a provider has already been made (whether successful
or not) then the default provider won't be loaded automatically. Therefore
if the default provider is to be used in conjunction with other providers
then it must be loaded explicitly. Automatic loading of the default
provider only occurs a maximum of once; if the default provider is
explicitly unloaded then the default provider will not be automatically
loaded again.
=head2 Properties
The implementations in this provider specifically have this property
defined:
=over 4
=item "provider=default"
=back
It may be used in a property query string with fetching functions such as
L<EVP_MD_fetch(3)> or L<EVP_CIPHER_fetch(3)>, as well as with other
functions that take a property query string, such as
L<EVP_PKEY_CTX_new_from_name(3)>.
It isn't mandatory to query for this property, except to make sure to get
implementations of this provider and none other.
Some implementations may define additional properties. Exact information is
listed below
=head1 OPERATIONS AND ALGORITHMS
The OpenSSL default provider supports these operations and algorithms:
=head2 Hashing Algorithms / Message Digests
=over 4
=item SHA1, see L<EVP_MD-SHA1(7)>
=item SHA2, see L<EVP_MD-SHA2(7)>
=item SHA3, see L<EVP_MD-SHA3(7)>
=item KECCAK-KMAC, see L<EVP_MD-KECCAK-KMAC(7)>
=item SHAKE, see L<EVP_MD-SHAKE(7)>
=item BLAKE2, see L<EVP_MD-BLAKE2(7)>
=item SM3, see L<EVP_MD-SM3(7)>
=item MD5, see L<EVP_MD-MD5(7)>
=item MD5-SHA1, see L<EVP_MD-MD5-SHA1(7)>
=item RIPEMD160, see L<EVP_MD-RIPEMD160(7)>
+=item NULL, see L<EVP_MD-NULL(7)>
+
=back
=head2 Symmetric Ciphers
=over 4
=item AES, see L<EVP_CIPHER-AES(7)>
=item ARIA, see L<EVP_CIPHER-ARIA(7)>
=item CAMELLIA, see L<EVP_CIPHER-CAMELLIA(7)>
=item 3DES, see L<EVP_CIPHER-DES(7)>
=item SEED, see L<EVP_CIPHER-SEED(7)>
=item SM4, see L<EVP_CIPHER-SM4(7)>
=item ChaCha20, see L<EVP_CIPHER-CHACHA(7)>
=item ChaCha20-Poly1305, see L<EVP_CIPHER-CHACHA(7)>
+=item NULL, see L<EVP_CIPHER-NULL(7)>
+
=back
=head2 Message Authentication Code (MAC)
=over 4
=item BLAKE2, see L<EVP_MAC-BLAKE2(7)>
=item CMAC, see L<EVP_MAC-CMAC(7)>
=item GMAC, see L<EVP_MAC-GMAC(7)>
=item HMAC, see L<EVP_MAC-HMAC(7)>
=item KMAC, see L<EVP_MAC-KMAC(7)>
=item SIPHASH, see L<EVP_MAC-Siphash(7)>
=item POLY1305, see L<EVP_MAC-Poly1305(7)>
=back
=head2 Key Derivation Function (KDF)
=over 4
=item HKDF, see L<EVP_KDF-HKDF(7)>
=item SSKDF, see L<EVP_KDF-SS(7)>
=item PBKDF2, see L<EVP_KDF-PBKDF2(7)>
=item PKCS12KDF, see L<EVP_KDF-PKCS12KDF(7)>
=item SSHKDF, see L<EVP_KDF-SSHKDF(7)>
=item TLS1-PRF, see L<EVP_KDF-TLS1_PRF(7)>
=item KBKDF, see L<EVP_KDF-KB(7)>
=item X942KDF-ASN1, see L<EVP_KDF-X942-ASN1(7)>
=item X942KDF-CONCAT, see L<EVP_KDF-X942-CONCAT(7)>
=item X963KDF, see L<EVP_KDF-X963(7)>
=item SCRYPT, see L<EVP_KDF-SCRYPT(7)>
=item KRB5KDF, see L<EVP_KDF-KRB5KDF(7)>
=back
=head2 Key Exchange
=over 4
=item DH, see L<EVP_KEYEXCH-DH(7)>
=item ECDH, see L<EVP_KEYEXCH-ECDH(7)>
=item X25519, see L<EVP_KEYEXCH-X25519(7)>
=item X448, see L<EVP_KEYEXCH-X448(7)>
=back
=head2 Asymmetric Signature
=over 4
=item DSA, see L<EVP_SIGNATURE-DSA(7)>
=item RSA, see L<EVP_SIGNATURE-RSA(7)>
=item HMAC, see L<EVP_SIGNATURE-HMAC(7)>
=item SIPHASH, see L<EVP_SIGNATURE-Siphash(7)>
=item POLY1305, see L<EVP_SIGNATURE-Poly1305(7)>
=item CMAC, see L<EVP_SIGNATURE-CMAC(7)>
=back
=head2 Asymmetric Cipher
=over 4
=item RSA, see L<EVP_ASYM_CIPHER-RSA(7)>
=item SM2, see L<EVP_ASYM_CIPHER-SM2(7)>
=back
=head2 Asymmetric Key Encapsulation
=over 4
=item RSA, see L<EVP_KEM-RSA(7)>
=back
=head2 Asymmetric Key Management
=over 4
=item DH, see L<EVP_KEYMGMT-DH(7)>
=item DHX, see L<EVP_KEYMGMT-DHX(7)>
=item DSA, see L<EVP_KEYMGMT-DSA(7)>
=item RSA, see L<EVP_KEYMGMT-RSA(7)>
=item EC, see L<EVP_KEYMGMT-EC(7)>
=item X25519, see L<EVP_KEYMGMT-X25519(7)>
=item X448, see L<EVP_KEYMGMT-X448(7)>
=back
+=head2 Random Number Generation
+
+=over 4
+
+=item CTR-DRBG, see L<EVP_RAND-CTR-DRBG(7)>
+
+=item HASH-DRBG, see L<EVP_RAND-HASH-DRBG(7)>
+
+=item HMAC-DRBG, see L<EVP_RAND-HMAC-DRBG(7)>
+
+=item SEED-SRC, see L<EVP_RAND-SEED-SRC(7)>
+
+=item TEST-RAND, see L<EVP_RAND-TEST-RAND(7)>
+
+=back
+
=head2 Asymmetric Key Encoder
The default provider also includes all of the encoding algorithms
present in the base provider. Some of these have the property "fips=yes",
to allow them to be used together with the FIPS provider.
=over 4
=item RSA, see L<OSSL_ENCODER-RSA(7)>
=item DH, see L<OSSL_ENCODER-DH(7)>
=item DSA, see L<OSSL_ENCODER-DSA(7)>
=item EC, see L<OSSL_ENCODER-EC(7)>
=item X25519, see L<OSSL_ENCODER-X25519(7)>
=item X448, see L<OSSL_ENCODER-X448(7)>
=back
=head1 SEE ALSO
L<openssl-core.h(7)>, L<openssl-core_dispatch.h(7)>, L<provider(7)>,
L<OSSL_PROVIDER-base(7)>
=head1 HISTORY
The RIPEMD160 digest was added to the default provider in OpenSSL 3.0.7.
All other functionality was added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man7/crypto.pod b/doc/man7/crypto.pod
index 59c60e4b5f92..ea81c91d3aff 100644
--- a/doc/man7/crypto.pod
+++ b/doc/man7/crypto.pod
@@ -1,514 +1,580 @@
=pod
=head1 NAME
crypto - OpenSSL cryptographic library
=head1 SYNOPSIS
See the individual manual pages for details.
=head1 DESCRIPTION
The OpenSSL crypto library (C<libcrypto>) implements a wide range of
cryptographic algorithms used in various Internet standards. The services
provided by this library are used by the OpenSSL implementations of TLS and
CMS, and they have also been used to implement many other third party products
and protocols.
The functionality includes symmetric encryption, public key cryptography, key
agreement, certificate handling, cryptographic hash functions, cryptographic
pseudo-random number generators, message authentication codes (MACs), key
derivation functions (KDFs), and various utilities.
=head2 Algorithms
Cryptographic primitives such as the SHA256 digest, or AES encryption are
referred to in OpenSSL as "algorithms". Each algorithm may have multiple
implementations available for use. For example the RSA algorithm is available as
a "default" implementation suitable for general use, and a "fips" implementation
which has been validated to FIPS standards for situations where that is
important. It is also possible that a third party could add additional
implementations such as in a hardware security module (HSM).
=head2 Operations
Different algorithms can be grouped together by their purpose. For example there
are algorithms for encryption, and different algorithms for digesting data.
These different groups are known as "operations" in OpenSSL. Each operation
has a different set of functions associated with it. For example to perform an
encryption operation using AES (or any other encryption algorithm) you would use
the encryption functions detailed on the L<EVP_EncryptInit(3)> page. Or to
perform a digest operation using SHA256 then you would use the digesting
functions on the L<EVP_DigestInit(3)> page.
=head2 Providers
A provider in OpenSSL is a component that collects together algorithm
implementations. In order to use an algorithm you must have at least one
provider loaded that contains an implementation of it. OpenSSL comes with a
number of providers and they may also be obtained from third parties. If you
don't load a provider explicitly (either in program code or via config) then the
OpenSSL built-in "default" provider will be automatically loaded.
=head2 Library contexts
A library context can be thought of as a "scope" within which configuration
options take effect. When a provider is loaded, it is only loaded within the
scope of a given library context. In this way it is possible for different
components of a complex application to each use a different library context and
have different providers loaded with different configuration settings.
If an application does not explicitly create a library context then the
"default" library context will be used.
Library contexts are represented by the B<OSSL_LIB_CTX> type. Many OpenSSL API
functions take a library context as a parameter. Applications can always pass
B<NULL> for this parameter to just use the default library context.
The default library context is automatically created the first time it is
needed. This will automatically load any available configuration file and will
initialise OpenSSL for use. Unlike in earlier versions of OpenSSL (prior to
1.1.0) no explicit initialisation steps need to be taken.
Similarly when the application exits the default library context is
automatically destroyed. No explicit de-initialisation steps need to be taken.
See L<OSSL_LIB_CTX(3)> for more information about library contexts.
See also L</ALGORITHM FETCHING>.
=head2 Multi-threaded applications
As long as OpenSSL has been built with support for threads (the default case
on most platforms) then most OpenSSL I<functions> are thread-safe in the sense
that it is safe to call the same function from multiple threads at the same
time. However most OpenSSL I<data structures> are not thread-safe. For example
the L<BIO_write(3)> and L<BIO_read(3)> functions are thread safe. However it
would not be thread safe to call BIO_write() from one thread while calling
BIO_read() in another where both functions are passed the same B<BIO> object
since both of them may attempt to make changes to the same B<BIO> object.
There are exceptions to these rules. A small number of functions are not thread
safe at all. Where this is the case this restriction should be noted in the
documentation for the function. Similarly some data structures may be partially
or fully thread safe. For example it is safe to use an B<OSSL_LIB_CTX> in
multiple threads.
See L<openssl-threads(7)> for a more detailed discussion on OpenSSL threading
support.
=head1 ALGORITHM FETCHING
In order to use an algorithm an implementation for it must first be "fetched".
Fetching is the process of looking through the available implementations,
applying selection criteria (via a property query string), and finally choosing
the implementation that will be used.
Two types of fetching are supported by OpenSSL - explicit fetching and implicit
fetching.
=head2 Property query strings
When fetching an algorithm it is possible to specify a property query string to
guide the selection process. For example a property query string of
"provider=default" could be used to force the selection to only consider
algorithm implementations in the default provider.
Property query strings can be specified explicitly as an argument to a function.
It is also possible to specify a default property query string for the whole
-library context using the L<EVP_set_default_properties(3)> function. Where both
+library context using the L<EVP_set_default_properties(3)> or
+L<EVP_default_properties_enable_fips(3)> functions. Where both
default properties and function specific properties are specified then they are
combined. Function specific properties will override default properties where
there is a conflict.
See L<property(7)> for more information about properties.
=head2 Explicit fetching
Users of the OpenSSL libraries never query a provider directly for an algorithm
implementation. Instead, the diverse OpenSSL APIs often have explicit fetching
functions that do the work, and they return an appropriate algorithm object back
to the user. These functions usually have the name C<APINAME_fetch>, where
C<APINAME> is the name of the operation. For example L<EVP_MD_fetch(3)> can
be used to explicitly fetch a digest algorithm implementation. The user is
responsible for freeing the object returned from the C<APINAME_fetch> function
using C<APINAME_free> when it is no longer needed.
These fetching functions follow a fairly common pattern, where three
arguments are passed:
=over 4
=item The library context
See L<OSSL_LIB_CTX(3)> for a more detailed description.
This may be NULL to signify the default (global) library context, or a
context created by the user. Only providers loaded in this library context (see
L<OSSL_PROVIDER_load(3)>) will be considered by the fetching function. In case
no provider has been loaded in this library context then the default provider
will be loaded as a fallback (see L<OSSL_PROVIDER-default(7)>).
=item An identifier
For all currently implemented fetching functions this is the algorithm name.
=item A property query string
The property query string used to guide selection of the algorithm
implementation.
=back
The algorithm implementation that is fetched can then be used with other diverse
functions that use them. For example the L<EVP_DigestInit_ex(3)> function takes
as a parameter an B<EVP_MD> object which may have been returned from an earlier
call to L<EVP_MD_fetch(3)>.
-=head2 Implicit fetch
+=head2 Implicit fetching
OpenSSL has a number of functions that return an algorithm object with no
associated implementation, such as L<EVP_sha256(3)>, L<EVP_aes_128_cbc(3)>,
L<EVP_get_cipherbyname(3)> or L<EVP_get_digestbyname(3)>. These are present for
compatibility with OpenSSL before version 3.0 where explicit fetching was not
available.
When they are used with functions like L<EVP_DigestInit_ex(3)> or
L<EVP_CipherInit_ex(3)>, the actual implementation to be used is
fetched implicitly using default search criteria.
In some cases implicit fetching can also occur when a NULL algorithm parameter
is supplied. In this case an algorithm implementation is implicitly fetched
using default search criteria and an algorithm name that is consistent with
the context in which it is being used.
Functions that revolve around B<EVP_PKEY_CTX> and L<EVP_PKEY(3)>, such as
L<EVP_DigestSignInit(3)> and friends, all fetch the implementations
implicitly. Because these functions involve both an operation type (such as
L<EVP_SIGNATURE(3)>) and an L<EVP_KEYMGMT(3)> for the L<EVP_PKEY(3)>, they try
the following:
=over 4
=item 1.
Fetch the operation type implementation from any provider given a library
context and property string stored in the B<EVP_PKEY_CTX>.
If the provider of the operation type implementation is different from the
provider of the L<EVP_PKEY(3)>'s L<EVP_KEYMGMT(3)> implementation, try to
fetch a L<EVP_KEYMGMT(3)> implementation in the same provider as the operation
type implementation and export the L<EVP_PKEY(3)> to it (effectively making a
temporary copy of the original key).
If anything in this step fails, the next step is used as a fallback.
=item 2.
As a fallback, try to fetch the operation type implementation from the same
provider as the original L<EVP_PKEY(3)>'s L<EVP_KEYMGMT(3)>, still using the
propery string from the B<EVP_PKEY_CTX>.
=back
+=head2 Performance
+
+If you perform the same operation many times then it is recommended to use
+L</Explicit fetching> to prefetch an algorithm once initially,
+and then pass this created object to any operations that are currently
+using L</Implicit fetching>.
+See an example of Explicit fetching in L</USING ALGORITHMS IN APPLICATIONS>.
+
+Prior to OpenSSL 3.0, constant method tables (such as EVP_sha256()) were used
+directly to access methods. If you pass one of these convenience functions
+to an operation the fixed methods are ignored, and only the name is used to
+internally fetch methods from a provider.
+
+If the prefetched object is not passed to operations, then any implicit
+fetch will use the internally cached prefetched object, but it will
+still be slower than passing the prefetched object directly.
+
+Fetching via a provider offers more flexibility, but it is slower than the
+old method, since it must search for the algorithm in all loaded providers,
+and then populate the method table using provider supplied methods.
+Internally OpenSSL caches similar algorithms on the first fetch
+(so loading a digest caches all digests).
+
+The following methods can be used for prefetching:
+
+=over 4
+
+=item L<EVP_MD_fetch(3)>
+
+=item L<EVP_CIPHER_fetch(3)>
+
+=item L<EVP_KDF_fetch(3)>
+
+=item L<EVP_MAC_fetch(3)>
+
+=item L<EVP_KEM_fetch(3)>
+
+=item L<OSSL_ENCODER_fetch(3)>
+
+=item L<OSSL_DECODER_fetch(3)>
+
+=item L<EVP_RAND_fetch(3)>
+
+=back
+
+The following methods are used internally when performing operations:
+
+=over 4
+
+=item L<EVP_KEYMGMT_fetch(3)>
+
+=item L<EVP_KEYEXCH_fetch(3)>
+
+=item L<EVP_SIGNATURE_fetch(3)>
+
+=item L<OSSL_STORE_LOADER_fetch(3)>
+
+=back
+
+See L<OSSL_PROVIDER-default(7)>, <OSSL_PROVIDER-fips(7)> and
+<OSSL_PROVIDER-legacy(7)>for a list of algorithm names that
+can be fetched.
+
=head1 FETCHING EXAMPLES
The following section provides a series of examples of fetching algorithm
implementations.
Fetch any available implementation of SHA2-256 in the default context. Note
that some algorithms have aliases. So "SHA256" and "SHA2-256" are synonymous:
EVP_MD *md = EVP_MD_fetch(NULL, "SHA2-256", NULL);
...
EVP_MD_free(md);
Fetch any available implementation of AES-128-CBC in the default context:
EVP_CIPHER *cipher = EVP_CIPHER_fetch(NULL, "AES-128-CBC", NULL);
...
EVP_CIPHER_free(cipher);
Fetch an implementation of SHA2-256 from the default provider in the default
context:
EVP_MD *md = EVP_MD_fetch(NULL, "SHA2-256", "provider=default");
...
EVP_MD_free(md);
Fetch an implementation of SHA2-256 that is not from the default provider in the
default context:
EVP_MD *md = EVP_MD_fetch(NULL, "SHA2-256", "provider!=default");
...
EVP_MD_free(md);
Fetch an implementation of SHA2-256 from the default provider in the specified
context:
EVP_MD *md = EVP_MD_fetch(ctx, "SHA2-256", "provider=default");
...
EVP_MD_free(md);
Load the legacy provider into the default context and then fetch an
implementation of WHIRLPOOL from it:
/* This only needs to be done once - usually at application start up */
OSSL_PROVIDER *legacy = OSSL_PROVIDER_load(NULL, "legacy");
EVP_MD *md = EVP_MD_fetch(NULL, "WHIRLPOOL", "provider=legacy");
...
EVP_MD_free(md);
Note that in the above example the property string "provider=legacy" is optional
since, assuming no other providers have been loaded, the only implementation of
the "whirlpool" algorithm is in the "legacy" provider. Also note that the
default provider should be explicitly loaded if it is required in addition to
other providers:
/* This only needs to be done once - usually at application start up */
OSSL_PROVIDER *legacy = OSSL_PROVIDER_load(NULL, "legacy");
OSSL_PROVIDER *default = OSSL_PROVIDER_load(NULL, "default");
EVP_MD *md_whirlpool = EVP_MD_fetch(NULL, "whirlpool", NULL);
EVP_MD *md_sha256 = EVP_MD_fetch(NULL, "SHA2-256", NULL);
...
EVP_MD_free(md_whirlpool);
EVP_MD_free(md_sha256);
=head1 OPENSSL PROVIDERS
OpenSSL comes with a set of providers.
The algorithms available in each of these providers may vary due to build time
configuration options. The L<openssl-list(1)> command can be used to list the
currently available algorithms.
The names of the algorithms shown from L<openssl-list(1)> can be used as an
algorithm identifier to the appropriate fetching function. Also see the provider
specific manual pages linked below for further details about using the
algorithms available in each of the providers.
As well as the OpenSSL providers third parties can also implement providers.
For information on writing a provider see L<provider(7)>.
=head2 Default provider
The default provider is built in as part of the F<libcrypto> library and
contains all of the most commonly used algorithm implementations. Should it be
needed (if other providers are loaded and offer implementations of the same
algorithms), the property query string "provider=default" can be used as a
search criterion for these implementations. The default provider includes all
of the functionality in the base provider below.
If you don't load any providers at all then the "default" provider will be
automatically loaded. If you explicitly load any provider then the "default"
provider would also need to be explicitly loaded if it is required.
See L<OSSL_PROVIDER-default(7)>.
=head2 Base provider
The base provider is built in as part of the F<libcrypto> library and contains
algorithm implementations for encoding and decoding for OpenSSL keys.
Should it be needed (if other providers are loaded and offer
implementations of the same algorithms), the property query string
"provider=base" can be used as a search criterion for these implementations.
Some encoding and decoding algorithm implementations are not FIPS algorithm
implementations in themselves but support algorithms from the FIPS provider and
are allowed for use in "FIPS mode". The property query string "fips=yes" can be
used to select such algorithms.
See L<OSSL_PROVIDER-base(7)>.
=head2 FIPS provider
The FIPS provider is a dynamically loadable module, and must therefore
be loaded explicitly, either in code or through OpenSSL configuration
(see L<config(5)>). It contains algorithm implementations that have been
validated according to the FIPS 140-2 standard. Should it be needed (if other
providers are loaded and offer implementations of the same algorithms), the
property query string "provider=fips" can be used as a search criterion for
these implementations. All approved algorithm implementations in the FIPS
provider can also be selected with the property "fips=yes". The FIPS provider
may also contain non-approved algorithm implementations and these can be
selected with the property "fips=no".
See L<OSSL_PROVIDER-FIPS(7)> and L<fips_module(7)>.
=head2 Legacy provider
The legacy provider is a dynamically loadable module, and must therefore
be loaded explicitly, either in code or through OpenSSL configuration
(see L<config(5)>). It contains algorithm implementations that are considered
insecure, or are no longer in common use such as MD2 or RC4. Should it be needed
(if other providers are loaded and offer implementations of the same algorithms),
the property "provider=legacy" can be used as a search criterion for these
implementations.
See L<OSSL_PROVIDER-legacy(7)>.
=head2 Null provider
The null provider is built in as part of the F<libcrypto> library. It contains
no algorithms in it at all. When fetching algorithms the default provider will
be automatically loaded if no other provider has been explicitly loaded. To
prevent that from happening you can explicitly load the null provider.
See L<OSSL_PROVIDER-null(7)>.
=head1 USING ALGORITHMS IN APPLICATIONS
Cryptographic algorithms are made available to applications through use of the
"EVP" APIs. Each of the various operations such as encryption, digesting,
message authentication codes, etc., have a set of EVP function calls that can
be invoked to use them. See the L<evp(7)> page for further details.
Most of these follow a common pattern. A "context" object is first created. For
example for a digest operation you would use an B<EVP_MD_CTX>, and for an
encryption/decryption operation you would use an B<EVP_CIPHER_CTX>. The
operation is then initialised ready for use via an "init" function - optionally
passing in a set of parameters (using the L<OSSL_PARAM(3)> type) to configure how
the operation should behave. Next data is fed into the operation in a series of
"update" calls. The operation is finalised using a "final" call which will
typically provide some kind of output. Finally the context is cleaned up and
freed.
The following shows a complete example for doing this process for digesting
data using SHA256. The process is similar for other operations such as
encryption/decryption, signatures, message authentication codes, etc.
#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
int main(void)
{
EVP_MD_CTX *ctx = NULL;
EVP_MD *sha256 = NULL;
const unsigned char msg[] = {
0x00, 0x01, 0x02, 0x03
};
unsigned int len = 0;
unsigned char *outdigest = NULL;
int ret = 1;
/* Create a context for the digest operation */
ctx = EVP_MD_CTX_new();
if (ctx == NULL)
goto err;
/*
* Fetch the SHA256 algorithm implementation for doing the digest. We're
* using the "default" library context here (first NULL parameter), and
* we're not supplying any particular search criteria for our SHA256
* implementation (second NULL parameter). Any SHA256 implementation will
* do.
+ * In a larger application this fetch would just be done once, and could
+ * be used for multiple calls to other operations such as EVP_DigestInit_ex().
*/
sha256 = EVP_MD_fetch(NULL, "SHA256", NULL);
if (sha256 == NULL)
goto err;
/* Initialise the digest operation */
if (!EVP_DigestInit_ex(ctx, sha256, NULL))
goto err;
/*
* Pass the message to be digested. This can be passed in over multiple
* EVP_DigestUpdate calls if necessary
*/
if (!EVP_DigestUpdate(ctx, msg, sizeof(msg)))
goto err;
/* Allocate the output buffer */
outdigest = OPENSSL_malloc(EVP_MD_get_size(sha256));
if (outdigest == NULL)
goto err;
/* Now calculate the digest itself */
if (!EVP_DigestFinal_ex(ctx, outdigest, &len))
goto err;
/* Print out the digest result */
BIO_dump_fp(stdout, outdigest, len);
ret = 0;
err:
/* Clean up all the resources we allocated */
OPENSSL_free(outdigest);
EVP_MD_free(sha256);
EVP_MD_CTX_free(ctx);
if (ret != 0)
ERR_print_errors_fp(stderr);
return ret;
}
=head1 CONFIGURATION
By default OpenSSL will load a configuration file when it is first used. This
will set up various configuration settings within the default library context.
Applications that create their own library contexts may optionally configure
them with a config file using the L<OSSL_LIB_CTX_load_config(3)> function.
The configuration file can be used to automatically load providers and set up
default property query strings.
For information on the OpenSSL configuration file format see L<config(5)>.
=head1 ENCODING AND DECODING KEYS
Many algorithms require the use of a key. Keys can be generated dynamically
using the EVP APIs (for example see L<EVP_PKEY_Q_keygen(3)>). However it is often
necessary to save or load keys (or their associated parameters) to or from some
external format such as PEM or DER (see L<openssl-glossary(7)>). OpenSSL uses
encoders and decoders to perform this task.
Encoders and decoders are just algorithm implementations in the same way as
any other algorithm implementation in OpenSSL. They are implemented by
providers. The OpenSSL encoders and decoders are available in the default
provider. They are also duplicated in the base provider.
For information about encoders see L<OSSL_ENCODER_CTX_new_for_pkey(3)>. For
information about decoders see L<OSSL_DECODER_CTX_new_for_pkey(3)>.
=head1 LIBRARY CONVENTIONS
Many OpenSSL functions that "get" or "set" a value follow a naming convention
using the numbers B<0> and B<1>, i.e. "get0", "get1", "set0" and "set1". This
can also apply to some functions that "add" a value to an existing set, i.e.
"add0" and "add1".
For example the functions:
int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
int X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj);
In the B<0> version the ownership of the object is passed to (for an add or set)
or retained by (for a get) the parent object. For example after calling the
X509_CRL_add0_revoked() function above, ownership of the I<rev> object is passed
to the I<crl> object. Therefore, after calling this function I<rev> should not
be freed directly. It will be freed implicitly when I<crl> is freed.
In the B<1> version the ownership of the object is not passed to or retained by
the parent object. Instead a copy or "up ref" of the object is performed. So
after calling the X509_add1_trust_object() function above the application will
still be responsible for freeing the I<obj> value where appropriate.
=head1 SEE ALSO
L<openssl(1)>, L<ssl(7)>, L<evp(7)>, L<OSSL_LIB_CTX(3)>, L<openssl-threads(7)>,
L<property(7)>, L<OSSL_PROVIDER-default(7)>, L<OSSL_PROVIDER-base(7)>,
L<OSSL_PROVIDER-FIPS(7)>, L<OSSL_PROVIDER-legacy(7)>, L<OSSL_PROVIDER-null(7)>,
L<openssl-glossary(7)>, L<provider(7)>
=head1 COPYRIGHT
-Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man7/migration_guide.pod b/doc/man7/migration_guide.pod
index a234147f46a0..9eb4a031aa32 100644
--- a/doc/man7/migration_guide.pod
+++ b/doc/man7/migration_guide.pod
@@ -1,2432 +1,2463 @@
=pod
=head1 NAME
migration_guide - OpenSSL migration guide
=head1 SYNOPSIS
See the individual manual pages for details.
=head1 DESCRIPTION
This guide details the changes required to migrate to new versions of OpenSSL.
Currently this covers OpenSSL 3.0. For earlier versions refer to
L<https://github.com/openssl/openssl/blob/master/CHANGES.md>.
For an overview of some of the key concepts introduced in OpenSSL 3.0 see
L<crypto(7)>.
=head1 OPENSSL 3.0
=head2 Main Changes from OpenSSL 1.1.1
=head3 Major Release
OpenSSL 3.0 is a major release and consequently any application that currently
uses an older version of OpenSSL will at the very least need to be recompiled in
order to work with the new version. It is the intention that the large majority
of applications will work unchanged with OpenSSL 3.0 if those applications
previously worked with OpenSSL 1.1.1. However this is not guaranteed and some
changes may be required in some cases. Changes may also be required if
applications need to take advantage of some of the new features available in
OpenSSL 3.0 such as the availability of the FIPS module.
=head3 License Change
In previous versions, OpenSSL was licensed under the L<dual OpenSSL and SSLeay
licenses|https://www.openssl.org/source/license-openssl-ssleay.txt>
(both licenses apply). From OpenSSL 3.0 this is replaced by the
L<Apache License v2|https://www.openssl.org/source/apache-license-2.0.txt>.
=head3 Providers and FIPS support
One of the key changes from OpenSSL 1.1.1 is the introduction of the Provider
concept. Providers collect together and make available algorithm implementations.
With OpenSSL 3.0 it is possible to specify, either programmatically or via a
config file, which providers you want to use for any given application.
OpenSSL 3.0 comes with 5 different providers as standard. Over time third
parties may distribute additional providers that can be plugged into OpenSSL.
All algorithm implementations available via providers are accessed through the
"high level" APIs (for example those functions prefixed with C<EVP>). They cannot
be accessed using the L</Low Level APIs>.
One of the standard providers available is the FIPS provider. This makes
available FIPS validated cryptographic algorithms.
The FIPS provider is disabled by default and needs to be enabled explicitly
at configuration time using the C<enable-fips> option. If it is enabled,
the FIPS provider gets built and installed in addition to the other standard
providers. No separate installation procedure is necessary.
There is however a dedicated C<install_fips> make target, which serves the
special purpose of installing only the FIPS provider into an existing
OpenSSL installation.
Not all algorithms may be available for the application at a particular moment.
If the application code uses any digest or cipher algorithm via the EVP interface,
the application should verify the result of the L<EVP_EncryptInit(3)>,
L<EVP_EncryptInit_ex(3)>, and L<EVP_DigestInit(3)> functions. In case when
the requested algorithm is not available, these functions will fail.
See also L</Legacy Algorithms> for information on the legacy provider.
See also L</Completing the installation of the FIPS Module> and
L</Using the FIPS Module in applications>.
=head3 Low Level APIs
OpenSSL has historically provided two sets of APIs for invoking cryptographic
algorithms: the "high level" APIs (such as the C<EVP> APIs) and the "low level"
APIs. The high level APIs are typically designed to work across all algorithm
types. The "low level" APIs are targeted at a specific algorithm implementation.
For example, the EVP APIs provide the functions L<EVP_EncryptInit_ex(3)>,
L<EVP_EncryptUpdate(3)> and L<EVP_EncryptFinal(3)> to perform symmetric
encryption. Those functions can be used with the algorithms AES, CHACHA, 3DES etc.
On the other hand, to do AES encryption using the low level APIs you would have
to call AES specific functions such as L<AES_set_encrypt_key(3)>,
L<AES_encrypt(3)>, and so on. The functions for 3DES are different.
Use of the low level APIs has been informally discouraged by the OpenSSL
development team for a long time. However in OpenSSL 3.0 this is made more
formal. All such low level APIs have been deprecated. You may still use them in
your applications, but you may start to see deprecation warnings during
compilation (dependent on compiler support for this). Deprecated APIs may be
removed from future versions of OpenSSL so you are strongly encouraged to update
your code to use the high level APIs instead.
This is described in more detail in L</Deprecation of Low Level Functions>
=head3 Legacy Algorithms
Some cryptographic algorithms such as B<MD2> and B<DES> that were available via
the EVP APIs are now considered legacy and their use is strongly discouraged.
These legacy EVP algorithms are still available in OpenSSL 3.0 but not by
default. If you want to use them then you must load the legacy provider.
This can be as simple as a config file change, or can be done programmatically.
See L<OSSL_PROVIDER-legacy(7)> for a complete list of algorithms.
Applications using the EVP APIs to access these algorithms should instead use
more modern algorithms. If that is not possible then these applications
should ensure that the legacy provider has been loaded. This can be achieved
either programmatically or via configuration. See L<crypto(7)> man page for
more information about providers.
=head3 Engines and "METHOD" APIs
The refactoring to support Providers conflicts internally with the APIs used to
support engines, including the ENGINE API and any function that creates or
modifies custom "METHODS" (for example L<EVP_MD_meth_new(3)>,
L<EVP_CIPHER_meth_new(3)>, L<EVP_PKEY_meth_new(3)>, L<RSA_meth_new(3)>,
L<EC_KEY_METHOD_new(3)>, etc.). These functions are being deprecated in
OpenSSL 3.0, and users of these APIs should know that their use can likely
bypass provider selection and configuration, with unintended consequences.
This is particularly relevant for applications written to use the OpenSSL 3.0
FIPS module, as detailed below. Authors and maintainers of external engines are
strongly encouraged to refactor their code transforming engines into providers
using the new Provider API and avoiding deprecated methods.
=head3 Support of legacy engines
If openssl is not built without engine support or deprecated API support, engines
will still work. However, their applicability will be limited.
New algorithms provided via engines will still work.
Engine-backed keys can be loaded via custom B<OSSL_STORE> implementation.
In this case the B<EVP_PKEY> objects created via L<ENGINE_load_private_key(3)>
will be concidered legacy and will continue to work.
To ensure the future compatibility, the engines should be turned to providers.
To prefer the provider-based hardware offload, you can specify the default
properties to prefer your provider.
=head3 Versioning Scheme
The OpenSSL versioning scheme has changed with the OpenSSL 3.0 release. The new
versioning scheme has this format:
MAJOR.MINOR.PATCH
For OpenSSL 1.1.1 and below, different patch levels were indicated by a letter
at the end of the release version number. This will no longer be used and
instead the patch level is indicated by the final number in the version. A
change in the second (MINOR) number indicates that new features may have been
added. OpenSSL versions with the same major number are API and ABI compatible.
If the major number changes then API and ABI compatibility is not guaranteed.
For more information, see L<OpenSSL_version(3)>.
=head3 Other major new features
=head4 Certificate Management Protocol (CMP, RFC 4210)
This also covers CRMF (RFC 4211) and HTTP transfer (RFC 6712)
See L<openssl-cmp(1)> and L<OSSL_CMP_exec_certreq(3)> as starting points.
=head4 HTTP(S) client
A proper HTTP(S) client that supports GET and POST, redirection, plain and
ASN.1-encoded contents, proxies, and timeouts.
=head4 Key Derivation Function API (EVP_KDF)
This simplifies the process of adding new KDF and PRF implementations.
Previously KDF algorithms had been shoe-horned into using the EVP_PKEY object
which was not a logical mapping.
Existing applications that use KDF algorithms using EVP_PKEY
(scrypt, TLS1 PRF and HKDF) may be slower as they use an EVP_KDF bridge
internally.
All new applications should use the new L<EVP_KDF(3)> interface.
See also L<OSSL_PROVIDER-default(7)/Key Derivation Function (KDF)> and
L<OSSL_PROVIDER-FIPS(7)/Key Derivation Function (KDF)>.
=head4 Message Authentication Code API (EVP_MAC)
This simplifies the process of 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
L<EVP_DigestSign(3)> and L<EVP_DigestVerify(3)>.
All new applications should use the new L<EVP_MAC(3)> interface.
See also L<OSSL_PROVIDER-default(7)/Message Authentication Code (MAC)>
and L<OSSL_PROVIDER-FIPS(7)/Message Authentication Code (MAC)>.
+=head4 Algorithm Fetching
+
+Using calls to convenience functions such as EVP_sha256() and EVP_aes_256_gcm() may
+incur a performance penalty when using providers.
+Retrieving algorithms from providers involves searching for an algorithm by name.
+This is much slower than directly accessing a method table.
+It is recommended to prefetch algorithms if an algorithm is used many times.
+See L<crypto(7)/Performance>, L<crypto(7)/Explicit fetching> and L<crypto(7)/Implicit fetching>.
+
=head4 Support for Linux Kernel TLS
In order to use KTLS, support for it must be compiled in using the
C<enable-ktls> configuration option. It must also be enabled at run time using
the B<SSL_OP_ENABLE_KTLS> option.
=head4 New Algorithms
=over 4
=item *
KDF algorithms "SINGLE STEP" and "SSH"
See L<EVP_KDF-SS(7)> and L<EVP_KDF-SSHKDF(7)>
=item *
MAC Algorithms "GMAC" and "KMAC"
See L<EVP_MAC-GMAC(7)> and L<EVP_MAC-KMAC(7)>.
=item *
KEM Algorithm "RSASVE"
See L<EVP_KEM-RSA(7)>.
=item *
Cipher Algorithm "AES-SIV"
See L<EVP_EncryptInit(3)/SIV Mode>.
=item *
AES Key Wrap inverse ciphers supported by EVP layer.
The inverse ciphers use AES decryption for wrapping, and AES encryption for
unwrapping. The algorithms are: "AES-128-WRAP-INV", "AES-192-WRAP-INV",
"AES-256-WRAP-INV", "AES-128-WRAP-PAD-INV", "AES-192-WRAP-PAD-INV" and
"AES-256-WRAP-PAD-INV".
=item *
CTS ciphers added to EVP layer.
The algorithms are "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".
CS1, CS2 and CS3 variants are supported.
=back
=head4 CMS and PKCS#7 updates
=over 4
=item *
Added CAdES-BES signature verification support.
=item *
Added CAdES-BES signature scheme and attributes support (RFC 5126) to CMS API.
=item *
Added AuthEnvelopedData content type structure (RFC 5083) using AES_GCM
This uses the AES-GCM parameter (RFC 5084) for the Cryptographic Message Syntax.
Its purpose is to support encryption and decryption of a digital envelope that
is both authenticated and encrypted using AES GCM mode.
=item *
L<PKCS7_get_octet_string(3)> and L<PKCS7_type_is_other(3)> were made public.
=back
=head4 PKCS#12 API updates
The default algorithms for pkcs12 creation with the PKCS12_create() function
were changed to more modern PBKDF2 and AES based algorithms. The default
MAC iteration count was changed to PKCS12_DEFAULT_ITER to make it equal
with the password-based encryption iteration count. The default digest
algorithm for the MAC computation was changed to SHA-256. The pkcs12
application now supports -legacy option that restores the previous
default algorithms to support interoperability with legacy systems.
Added enhanced PKCS#12 APIs which accept a library context B<OSSL_LIB_CTX>
and (where relevant) a property query. Other APIs which handle PKCS#7 and
PKCS#8 objects have also been enhanced where required. This includes:
L<PKCS12_add_key_ex(3)>, L<PKCS12_add_safe_ex(3)>, L<PKCS12_add_safes_ex(3)>,
L<PKCS12_create_ex(3)>, L<PKCS12_decrypt_skey_ex(3)>, L<PKCS12_init_ex(3)>,
L<PKCS12_item_decrypt_d2i_ex(3)>, L<PKCS12_item_i2d_encrypt_ex(3)>,
L<PKCS12_key_gen_asc_ex(3)>, L<PKCS12_key_gen_uni_ex(3)>, L<PKCS12_key_gen_utf8_ex(3)>,
L<PKCS12_pack_p7encdata_ex(3)>, L<PKCS12_pbe_crypt_ex(3)>, L<PKCS12_PBE_keyivgen_ex(3)>,
L<PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(3)>, L<PKCS5_pbe2_set_iv_ex(3)>,
L<PKCS5_pbe_set0_algor_ex(3)>, L<PKCS5_pbe_set_ex(3)>, L<PKCS5_pbkdf2_set_ex(3)>,
L<PKCS5_v2_PBE_keyivgen_ex(3)>, L<PKCS5_v2_scrypt_keyivgen_ex(3)>,
L<PKCS8_decrypt_ex(3)>, L<PKCS8_encrypt_ex(3)>, L<PKCS8_set0_pbe_ex(3)>.
As part of this change the EVP_PBE_xxx APIs can also accept a library
context and property query and will call an extended version of the key/IV
derivation function which supports these parameters. This includes
L<EVP_PBE_CipherInit_ex(3)>, L<EVP_PBE_find_ex(3)> and L<EVP_PBE_scrypt_ex(3)>.
=head4 Windows thread synchronization changes
Windows thread synchronization uses read/write primitives (SRWLock) when
supported by the OS, otherwise CriticalSection continues to be used.
=head4 Trace API
A new generic trace API has been added which provides support for enabling
instrumentation through trace output. This feature is mainly intended as an aid
for developers and is disabled by default. To utilize it, OpenSSL needs to be
configured with the C<enable-trace> option.
If the tracing API is enabled, the application can activate trace output by
registering BIOs as trace channels for a number of tracing and debugging
categories. See L<OSSL_trace_enabled(3)>.
=head4 Key validation updates
L<EVP_PKEY_public_check(3)> and L<EVP_PKEY_param_check(3)> now work for
more key types. This includes RSA, DSA, ED25519, X25519, ED448 and X448.
Previously (in 1.1.1) they would return -2. For key types that do not have
parameters then L<EVP_PKEY_param_check(3)> will always return 1.
=head3 Other notable deprecations and changes
=head4 The function code part of an OpenSSL error code is no longer relevant
This code is now always set to zero. Related functions are deprecated.
=head4 STACK and HASH macros have been cleaned up
The type-safe wrappers are declared everywhere and implemented once.
See L<DEFINE_STACK_OF(3)> and L<DECLARE_LHASH_OF(3)>.
=head4 The RAND_DRBG subsystem has been removed
The new L<EVP_RAND(3)> is a partial replacement: the DRBG callback framework is
absent. The RAND_DRBG API did not fit well into the new provider concept as
implemented by EVP_RAND and EVP_RAND_CTX.
=head4 Removed FIPS_mode() and FIPS_mode_set()
These functions are legacy APIs that are not applicable to the new provider
model. Applications should instead use
L<EVP_default_properties_is_fips_enabled(3)> and
L<EVP_default_properties_enable_fips(3)>.
=head4 Key generation is slower
The Miller-Rabin test now uses 64 rounds, which is used for all prime generation,
including RSA key generation. This affects the time for larger keys sizes.
The default key generation method for the regular 2-prime RSA keys was changed
to the FIPS186-4 B.3.6 method (Generation of Probable Primes with Conditions
Based on Auxiliary Probable Primes). This method is slower than the original
method.
=head4 Change PBKDF2 to conform to SP800-132 instead of the older PKCS5 RFC2898
This checks that the salt length is at least 128 bits, the derived key length is
at least 112 bits, and that the iteration count is at least 1000.
For backwards compatibility these checks are disabled by default in the
default provider, but are enabled by default in the FIPS provider.
To enable or disable the checks see B<OSSL_KDF_PARAM_PKCS5> in
L<EVP_KDF-PBKDF2(7)>. The parameter can be set using L<EVP_KDF_derive(3)>.
=head4 Enforce a minimum DH modulus size of 512 bits
Smaller sizes now result in an error.
=head4 SM2 key changes
EC EVP_PKEYs with the SM2 curve have been reworked to automatically become
EVP_PKEY_SM2 rather than EVP_PKEY_EC.
Unlike in previous OpenSSL versions, this means that applications cannot
call C<EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)> to get SM2 computations.
Parameter and key generation is also reworked to make it possible
to generate EVP_PKEY_SM2 parameters and keys. Applications must now generate
SM2 keys directly and must not create an EVP_PKEY_EC key first. It is no longer
possible to import an SM2 key with domain parameters other than the SM2 elliptic
curve ones.
Validation of SM2 keys has been separated from the validation of regular EC
keys, allowing to improve the SM2 validation process to reject loaded private
keys that are not conforming to the SM2 ISO standard.
In particular, a private scalar I<k> outside the range I<< 1 <= k < n-1 >> is
now correctly rejected.
=head4 EVP_PKEY_set_alias_type() method has been removed
This function made a B<EVP_PKEY> object mutable after it had been set up. In
OpenSSL 3.0 it was decided that a provided key should not be able to change its
type, so this function has been removed.
=head4 Functions that return an internal key should be treated as read only
Functions such as L<EVP_PKEY_get0_RSA(3)> behave slightly differently in
OpenSSL 3.0. Previously they returned a pointer to the low-level key used
internally by libcrypto. From OpenSSL 3.0 this key may now be held in a
provider. Calling these functions will only return a handle on the internal key
where the EVP_PKEY was constructed using this key in the first place, for
example using a function or macro such as L<EVP_PKEY_assign_RSA(3)>,
L<EVP_PKEY_set1_RSA(3)>, etc.
Where the EVP_PKEY holds a provider managed key, then these functions now return
a cached copy of the key. Changes to the internal provider key that take place
after the first time the cached key is accessed will not be reflected back in
the cached copy. Similarly any changes made to the cached copy by application
code will not be reflected back in the internal provider key.
For the above reasons the keys returned from these functions should typically be
treated as read-only. To emphasise this the value returned from
L<EVP_PKEY_get0_RSA(3)>, L<EVP_PKEY_get0_DSA(3)>, L<EVP_PKEY_get0_EC_KEY(3)> and
L<EVP_PKEY_get0_DH(3)> have been made const. This may break some existing code.
Applications broken by this change should be modified. The preferred solution is
to refactor the code to avoid the use of these deprecated functions. Failing
this the code should be modified to use a const pointer instead.
The L<EVP_PKEY_get1_RSA(3)>, L<EVP_PKEY_get1_DSA(3)>, L<EVP_PKEY_get1_EC_KEY(3)>
and L<EVP_PKEY_get1_DH(3)> functions continue to return a non-const pointer to
enable them to be "freed". However they should also be treated as read-only.
=head4 The public key check has moved from EVP_PKEY_derive() to EVP_PKEY_derive_set_peer()
This may mean result in an error in L<EVP_PKEY_derive_set_peer(3)> rather than
during L<EVP_PKEY_derive(3)>.
To disable this check use EVP_PKEY_derive_set_peer_ex(dh, peer, 0).
=head4 The print format has cosmetic changes for some functions
The output from numerous "printing" functions such as L<X509_signature_print(3)>,
L<X509_print_ex(3)>, L<X509_CRL_print_ex(3)>, and other similar functions has been
amended such that there may be cosmetic differences between the output
observed in 1.1.1 and 3.0. This also applies to the B<-text> output from the
B<openssl x509> and B<openssl crl> applications.
=head4 Interactive mode from the B<openssl> program has been removed
From now on, running it without arguments is equivalent to B<openssl help>.
=head4 The error return values from some control calls (ctrl) have changed
One significant change is that controls which used to return -2 for
invalid inputs, now return -1 indicating a generic error condition instead.
=head4 DH and DHX key types have different settable parameters
Previously (in 1.1.1) these conflicting parameters were allowed, but will now
result in errors. See L<EVP_PKEY-DH(7)> for further details. This affects the
behaviour of L<openssl-genpkey(1)> for DH parameter generation.
=head4 EVP_CIPHER_CTX_set_flags() ordering change
If using a cipher from a provider the B<EVP_CIPH_FLAG_LENGTH_BITS> flag can only
be set B<after> the cipher has been assigned to the cipher context.
See L<EVP_EncryptInit(3)/FLAGS> for more information.
=head4 Validation of operation context parameters
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.
=head4 Removal of function code from the error codes
The function code part of the error code is now always set to 0. For that
reason the ERR_GET_FUNC() macro was removed. Applications must resolve
the error codes only using the library number and the reason code.
=head4 ChaCha20-Poly1305 cipher does not allow a truncated IV length to be used
In OpenSSL 3.0 setting the IV length to any value other than 12 will result in an
error.
Prior to OpenSSL 3.0 the ivlen could be smaller that the required 12 byte length,
using EVP_CIPHER_CTX_ctrl(ctx, EVP_CRTL_AEAD_SET_IVLEN, ivlen, NULL). This resulted
in an IV that had leading zero padding.
=head2 Installation and Compilation
Please refer to the INSTALL.md file in the top of the distribution for
instructions on how to build and install OpenSSL 3.0. Please also refer to the
various platform specific NOTES files for your specific platform.
=head2 Upgrading from OpenSSL 1.1.1
Upgrading to OpenSSL 3.0 from OpenSSL 1.1.1 should be relatively straight
forward in most cases. The most likely area where you will encounter problems
is if you have used low level APIs in your code (as discussed above). In that
case you are likely to start seeing deprecation warnings when compiling your
application. If this happens you have 3 options:
=over 4
=item 1.
Ignore the warnings. They are just warnings. The deprecated functions are still present and you may still use them. However be aware that they may be removed from a future version of OpenSSL.
=item 2.
Suppress the warnings. Refer to your compiler documentation on how to do this.
=item 3.
Remove your usage of the low level APIs. In this case you will need to rewrite your code to use the high level APIs instead
=back
=head3 Error code changes
As OpenSSL 3.0 provides a brand new Encoder/Decoder mechanism for working with
widely used file formats, application code that checks for particular error
reason codes on key loading failures might need an update.
Password-protected keys may deserve special attention. If only some errors
are treated as an indicator that the user should be asked about the password again,
it's worth testing these scenarios and processing the newly relevant codes.
There may be more cases to treat specially, depending on the calling application code.
=head2 Upgrading from OpenSSL 1.0.2
Upgrading to OpenSSL 3.0 from OpenSSL 1.0.2 is likely to be significantly more
difficult. In addition to the issues discussed above in the section about
L</Upgrading from OpenSSL 1.1.1>, the main things to be aware of are:
=over 4
=item 1.
The build and installation procedure has changed significantly.
Check the file INSTALL.md in the top of the installation for instructions on how
to build and install OpenSSL for your platform. Also read the various NOTES
files in the same directory, as applicable for your platform.
=item 2.
Many structures have been made opaque in OpenSSL 3.0.
The structure definitions have been removed from the public header files and
moved to internal header files. In practice this means that you can no longer
stack allocate some structures. Instead they must be heap allocated through some
function call (typically those function names have a C<_new> suffix to them).
Additionally you must use "setter" or "getter" functions to access the fields
within those structures.
For example code that previously looked like this:
EVP_MD_CTX md_ctx;
/* This line will now generate compiler errors */
EVP_MD_CTX_init(&md_ctx);
The code needs to be amended to look like this:
EVP_MD_CTX *md_ctx;
md_ctx = EVP_MD_CTX_new();
...
...
EVP_MD_CTX_free(md_ctx);
=item 3.
Support for TLSv1.3 has been added.
This has a number of implications for SSL/TLS applications. See the
L<TLS1.3 page|https://wiki.openssl.org/index.php/TLS1.3> for further details.
=back
More details about the breaking changes between OpenSSL versions 1.0.2 and 1.1.0
can be found on the
L<OpenSSL 1.1.0 Changes page|https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes>.
=head3 Upgrading from the OpenSSL 2.0 FIPS Object Module
The OpenSSL 2.0 FIPS Object Module was a separate download that had to be built
separately and then integrated into your main OpenSSL 1.0.2 build.
In OpenSSL 3.0 the FIPS support is fully integrated into the mainline version of
OpenSSL and is no longer a separate download. For further information see
L</Completing the installation of the FIPS Module>.
The function calls FIPS_mode() and FIPS_mode_set() have been removed
from OpenSSL 3.0. You should rewrite your application to not use them.
See L<fips_module(7)> and L<OSSL_PROVIDER-FIPS(7)> for details.
=head2 Completing the installation of the FIPS Module
The FIPS Module will be built and installed automatically if FIPS support has
been configured. The current documentation can be found in the
L<README-FIPS|https://github.com/openssl/openssl/blob/master/README-FIPS.md> file.
=head2 Programming
Applications written to work with OpenSSL 1.1.1 will mostly just work with
OpenSSL 3.0. However changes will be required if you want to take advantage of
some of the new features that OpenSSL 3.0 makes available. In order to do that
you need to understand some new concepts introduced in OpenSSL 3.0.
Read L<crypto(7)/Library contexts> for further information.
=head3 Library Context
A library context allows different components of a complex application to each
use a different library context and have different providers loaded with
different configuration settings.
See L<crypto(7)/Library contexts> for further info.
If the user creates an B<OSSL_LIB_CTX> via L<OSSL_LIB_CTX_new(3)> then many
functions may need to be changed to pass additional parameters to handle the
library context.
=head4 Using a Library Context - Old functions that should be changed
If a library context is needed then all EVP_* digest functions that return a
B<const EVP_MD *> such as EVP_sha256() should be replaced with a call to
L<EVP_MD_fetch(3)>. See L<crypto(7)/ALGORITHM FETCHING>.
If a library context is needed then all EVP_* cipher functions that return a
B<const EVP_CIPHER *> such as EVP_aes_128_cbc() should be replaced vith a call to
L<EVP_CIPHER_fetch(3)>. See L<crypto(7)/ALGORITHM FETCHING>.
Some functions can be passed an object that has already been set up with a library
context such as L<d2i_X509(3)>, L<d2i_X509_CRL(3)>, L<d2i_X509_REQ(3)> and
L<d2i_X509_PUBKEY(3)>. If NULL is passed instead then the created object will be
set up with the default library context. Use L<X509_new_ex(3)>,
L<X509_CRL_new_ex(3)>, L<X509_REQ_new_ex(3)> and L<X509_PUBKEY_new_ex(3)> if a
library context is required.
All functions listed below with a I<NAME> have a replacment function I<NAME_ex>
that takes B<OSSL_LIB_CTX> as an additional argument. Functions that have other
mappings are listed along with the respective name.
=over 4
=item *
L<ASN1_item_new(3)>, L<ASN1_item_d2i(3)>, L<ASN1_item_d2i_fp(3)>,
L<ASN1_item_d2i_bio(3)>, L<ASN1_item_sign(3)> and L<ASN1_item_verify(3)>
=item *
L<BIO_new(3)>
=item *
b2i_RSA_PVK_bio() and i2b_PVK_bio()
=item *
L<BN_CTX_new(3)> and L<BN_CTX_secure_new(3)>
=item *
L<CMS_AuthEnvelopedData_create(3)>, L<CMS_ContentInfo_new(3)>, L<CMS_data_create(3)>,
L<CMS_digest_create(3)>, L<CMS_EncryptedData_encrypt(3)>, L<CMS_encrypt(3)>,
L<CMS_EnvelopedData_create(3)>, L<CMS_ReceiptRequest_create0(3)> and L<CMS_sign(3)>
=item *
L<CONF_modules_load_file(3)>
=item *
L<CTLOG_new(3)>, L<CTLOG_new_from_base64(3)> and L<CTLOG_STORE_new(3)>
=item *
L<CT_POLICY_EVAL_CTX_new(3)>
=item *
L<d2i_AutoPrivateKey(3)>, L<d2i_PrivateKey(3)> and L<d2i_PUBKEY(3)>
=item *
L<d2i_PrivateKey_bio(3)> and L<d2i_PrivateKey_fp(3)>
Use L<d2i_PrivateKey_ex_bio(3)> and L<d2i_PrivateKey_ex_fp(3)>
=item *
L<EC_GROUP_new(3)>
Use L<EC_GROUP_new_by_curve_name_ex(3)> or L<EC_GROUP_new_from_params(3)>.
=item *
L<EVP_DigestSignInit(3)> and L<EVP_DigestVerifyInit(3)>
=item *
L<EVP_PBE_CipherInit(3)>, L<EVP_PBE_find(3)> and L<EVP_PBE_scrypt(3)>
=item *
L<PKCS5_PBE_keyivgen(3)>
=item *
L<EVP_PKCS82PKEY(3)>
=item *
L<EVP_PKEY_CTX_new_id(3)>
Use L<EVP_PKEY_CTX_new_from_name(3)>
=item *
L<EVP_PKEY_derive_set_peer(3)>, L<EVP_PKEY_new_raw_private_key(3)>
and L<EVP_PKEY_new_raw_public_key(3)>
=item *
L<EVP_SignFinal(3)> and L<EVP_VerifyFinal(3)>
=item *
L<NCONF_new(3)>
=item *
L<OCSP_RESPID_match(3)> and L<OCSP_RESPID_set_by_key(3)>
=item *
L<OPENSSL_thread_stop(3)>
=item *
L<OSSL_STORE_open(3)>
=item *
L<PEM_read_bio_Parameters(3)>, L<PEM_read_bio_PrivateKey(3)>, L<PEM_read_bio_PUBKEY(3)>,
L<PEM_read_PrivateKey(3)> and L<PEM_read_PUBKEY(3)>
=item *
L<PEM_write_bio_PrivateKey(3)>, L<PEM_write_bio_PUBKEY(3)>, L<PEM_write_PrivateKey(3)>
and L<PEM_write_PUBKEY(3)>
=item *
L<PEM_X509_INFO_read_bio(3)> and L<PEM_X509_INFO_read(3)>
=item *
L<PKCS12_add_key(3)>, L<PKCS12_add_safe(3)>, L<PKCS12_add_safes(3)>,
L<PKCS12_create(3)>, L<PKCS12_decrypt_skey(3)>, L<PKCS12_init(3)>, L<PKCS12_item_decrypt_d2i(3)>,
L<PKCS12_item_i2d_encrypt(3)>, L<PKCS12_key_gen_asc(3)>, L<PKCS12_key_gen_uni(3)>,
L<PKCS12_key_gen_utf8(3)>, L<PKCS12_pack_p7encdata(3)>, L<PKCS12_pbe_crypt(3)>,
L<PKCS12_PBE_keyivgen(3)>, L<PKCS12_SAFEBAG_create_pkcs8_encrypt(3)>
=item *
L<PKCS5_pbe_set0_algor(3)>, L<PKCS5_pbe_set(3)>, L<PKCS5_pbe2_set_iv(3)>,
L<PKCS5_pbkdf2_set(3)> and L<PKCS5_v2_scrypt_keyivgen(3)>
=item *
L<PKCS7_encrypt(3)>, L<PKCS7_new(3)> and L<PKCS7_sign(3)>
=item *
L<PKCS8_decrypt(3)>, L<PKCS8_encrypt(3)> and L<PKCS8_set0_pbe(3)>
=item *
L<RAND_bytes(3)> and L<RAND_priv_bytes(3)>
=item *
L<SMIME_write_ASN1(3)>
=item *
L<SSL_load_client_CA_file(3)>
=item *
L<SSL_CTX_new(3)>
=item *
L<TS_RESP_CTX_new(3)>
=item *
L<X509_CRL_new(3)>
=item *
L<X509_load_cert_crl_file(3)> and L<X509_load_cert_file(3)>
=item *
L<X509_LOOKUP_by_subject(3)> and L<X509_LOOKUP_ctrl(3)>
=item *
L<X509_NAME_hash(3)>
=item *
L<X509_new(3)>
=item *
L<X509_REQ_new(3)> and L<X509_REQ_verify(3)>
=item *
L<X509_STORE_CTX_new(3)>, L<X509_STORE_set_default_paths(3)>, L<X509_STORE_load_file(3)>,
L<X509_STORE_load_locations(3)> and L<X509_STORE_load_store(3)>
=back
=head4 New functions that use a Library context
The following functions can be passed a library context if required.
Passing NULL will use the default library context.
=over 4
=item *
L<BIO_new_from_core_bio(3)>
=item *
L<EVP_ASYM_CIPHER_fetch(3)> and L<EVP_ASYM_CIPHER_do_all_provided(3)>
=item *
L<EVP_CIPHER_fetch(3)> and L<EVP_CIPHER_do_all_provided(3)>
=item *
L<EVP_default_properties_enable_fips(3)> and
L<EVP_default_properties_is_fips_enabled(3)>
=item *
L<EVP_KDF_fetch(3)> and L<EVP_KDF_do_all_provided(3)>
=item *
L<EVP_KEM_fetch(3)> and L<EVP_KEM_do_all_provided(3)>
=item *
L<EVP_KEYEXCH_fetch(3)> and L<EVP_KEYEXCH_do_all_provided(3)>
=item *
L<EVP_KEYMGMT_fetch(3)> and L<EVP_KEYMGMT_do_all_provided(3)>
=item *
L<EVP_MAC_fetch(3)> and L<EVP_MAC_do_all_provided(3)>
=item *
L<EVP_MD_fetch(3)> and L<EVP_MD_do_all_provided(3)>
=item *
L<EVP_PKEY_CTX_new_from_pkey(3)>
=item *
L<EVP_PKEY_Q_keygen(3)>
=item *
L<EVP_Q_mac(3)> and L<EVP_Q_digest(3)>
=item *
L<EVP_RAND(3)> and L<EVP_RAND_do_all_provided(3)>
=item *
L<EVP_set_default_properties(3)>
=item *
L<EVP_SIGNATURE_fetch(3)> and L<EVP_SIGNATURE_do_all_provided(3)>
=item *
L<OSSL_CMP_CTX_new(3)> and L<OSSL_CMP_SRV_CTX_new(3)>
=item *
L<OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(3)>
=item *
L<OSSL_CRMF_MSG_create_popo(3)> and L<OSSL_CRMF_MSGS_verify_popo(3)>
=item *
L<OSSL_CRMF_pbm_new(3)> and L<OSSL_CRMF_pbmp_new(3)>
=item *
L<OSSL_DECODER_CTX_add_extra(3)> and L<OSSL_DECODER_CTX_new_for_pkey(3)>
=item *
L<OSSL_DECODER_fetch(3)> and L<OSSL_DECODER_do_all_provided(3)>
=item *
L<OSSL_ENCODER_CTX_add_extra(3)>
=item *
L<OSSL_ENCODER_fetch(3)> and L<OSSL_ENCODER_do_all_provided(3)>
=item *
L<OSSL_LIB_CTX_free(3)>, L<OSSL_LIB_CTX_load_config(3)> and L<OSSL_LIB_CTX_set0_default(3)>
=item *
L<OSSL_PROVIDER_add_builtin(3)>, L<OSSL_PROVIDER_available(3)>,
L<OSSL_PROVIDER_do_all(3)>, L<OSSL_PROVIDER_load(3)>,
L<OSSL_PROVIDER_set_default_search_path(3)> and L<OSSL_PROVIDER_try_load(3)>
=item *
L<OSSL_SELF_TEST_get_callback(3)> and L<OSSL_SELF_TEST_set_callback(3)>
=item *
L<OSSL_STORE_attach(3)>
=item *
L<OSSL_STORE_LOADER_fetch(3)> and L<OSSL_STORE_LOADER_do_all_provided(3)>
=item *
L<RAND_get0_primary(3)>, L<RAND_get0_private(3)>, L<RAND_get0_public(3)>,
L<RAND_set_DRBG_type(3)> and L<RAND_set_seed_source_type(3)>
=back
=head3 Providers
Providers are described in detail here L<crypto(7)/Providers>.
See also L<crypto(7)/OPENSSL PROVIDERS>.
=head3 Fetching algorithms and property queries
Implicit and Explicit Fetching is described in detail here
L<crypto(7)/ALGORITHM FETCHING>.
=head3 Mapping EVP controls and flags to provider L<OSSL_PARAM(3)> parameters
The existing functions for controls (such as L<EVP_CIPHER_CTX_ctrl(3)>) and
manipulating flags (such as L<EVP_MD_CTX_set_flags(3)>)internally use
B<OSSL_PARAMS> to pass information to/from provider objects.
See L<OSSL_PARAM(3)> for additional information related to parameters.
For ciphers see L<EVP_EncryptInit(3)/CONTROLS>, L<EVP_EncryptInit(3)/FLAGS> and
L<EVP_EncryptInit(3)/PARAMETERS>.
For digests see L<EVP_DigestInit(3)/CONTROLS>, L<EVP_DigestInit(3)/FLAGS> and
L<EVP_DigestInit(3)/PARAMETERS>.
=head3 Deprecation of Low Level Functions
A significant number of APIs have been deprecated in OpenSSL 3.0.
This section describes some common categories of deprecations.
See L</Deprecated function mappings> for the list of deprecated functions
that refer to these categories.
=head4 Providers are a replacement for engines and low-level method overrides
Any accessor that uses an ENGINE is deprecated (such as EVP_PKEY_set1_engine()).
Applications using engines should instead use providers.
Before providers were added algorithms were overriden by changing the methods
used by algorithms. All these methods such as RSA_new_method() and RSA_meth_new()
are now deprecated and can be replaced by using providers instead.
=head4 Deprecated i2d and d2i functions for low-level key types
Any i2d and d2i functions such as d2i_DHparams() that take a low-level key type
have been deprecated. Applications should instead use the L<OSSL_DECODER(3)> and
L<OSSL_ENCODER(3)> APIs to read and write files.
See L<d2i_RSAPrivateKey(3)/Migration> for further details.
=head4 Deprecated low-level key object getters and setters
Applications that set or get low-level key objects (such as EVP_PKEY_set1_DH()
or EVP_PKEY_get0()) should instead use the OSSL_ENCODER
(See L<OSSL_ENCODER_to_bio(3)>) or OSSL_DECODER (See L<OSSL_DECODER_from_bio(3)>)
APIs, or alternatively use L<EVP_PKEY_fromdata(3)> or L<EVP_PKEY_todata(3)>.
=head4 Deprecated low-level key parameter getters
Functions that access low-level objects directly such as L<RSA_get0_n(3)> are now
deprecated. Applications should use one of L<EVP_PKEY_get_bn_param(3)>,
L<EVP_PKEY_get_int_param(3)>, l<EVP_PKEY_get_size_t_param(3)>,
L<EVP_PKEY_get_utf8_string_param(3)>, L<EVP_PKEY_get_octet_string_param(3)> or
L<EVP_PKEY_get_params(3)> to access fields from an EVP_PKEY.
Gettable parameters are listed in L<EVP_PKEY-RSA(7)/Common RSA parameters>,
L<EVP_PKEY-DH(7)/DH parameters>, L<EVP_PKEY-DSA(7)/DSA parameters>,
L<EVP_PKEY-FFC(7)/FFC parameters>, L<EVP_PKEY-EC(7)/Common EC parameters> and
L<EVP_PKEY-X25519(7)/Common X25519, X448, ED25519 and ED448 parameters>.
Applications may also use L<EVP_PKEY_todata(3)> to return all fields.
=head4 Deprecated low-level key parameter setters
Functions that access low-level objects directly such as L<RSA_set0_crt_params(3)>
are now deprecated. Applications should use L<EVP_PKEY_fromdata(3)> to create
new keys from user provided key data. Keys should be immutable once they are
created, so if required the user may use L<EVP_PKEY_todata(3)>, L<OSSL_PARAM_merge(3)>,
and L<EVP_PKEY_fromdata(3)> to create a modified key.
See L<EVP_PKEY-DH(7)/Examples> for more information.
See L</Deprecated low-level key generation functions> for information on
generating a key using parameters.
=head4 Deprecated low-level object creation
Low-level objects were created using methods such as L<RSA_new(3)>,
L<RSA_up_ref(3)> and L<RSA_free(3)>. Applications should instead use the
high-level EVP_PKEY APIs, e.g. L<EVP_PKEY_new(3)>, L<EVP_PKEY_up_ref(3)> and
L<EVP_PKEY_free(3)>.
See also L<EVP_PKEY_CTX_new_from_name(3)> and L<EVP_PKEY_CTX_new_from_pkey(3)>.
EVP_PKEYs may be created in a variety of ways:
See also L</Deprecated low-level key generation functions>,
L</Deprecated low-level key reading and writing functions> and
L</Deprecated low-level key parameter setters>.
=head4 Deprecated low-level encryption functions
Low-level encryption functions such as L<AES_encrypt(3)> and L<AES_decrypt(3)>
have been informally discouraged from use for a long time. Applications should
instead use the high level EVP APIs L<EVP_EncryptInit_ex(3)>,
L<EVP_EncryptUpdate(3)>, and L<EVP_EncryptFinal_ex(3)> or
L<EVP_DecryptInit_ex(3)>, L<EVP_DecryptUpdate(3)> and L<EVP_DecryptFinal_ex(3)>.
=head4 Deprecated low-level digest functions
Use of low-level digest functions such as L<SHA1_Init(3)> have been
informally discouraged from use for a long time. Applications should instead
use the the high level EVP APIs L<EVP_DigestInit_ex(3)>, L<EVP_DigestUpdate(3)>
and L<EVP_DigestFinal_ex(3)>, or the quick one-shot L<EVP_Q_digest(3)>.
Note that the functions L<SHA1(3)>, L<SHA224(3)>, L<SHA256(3)>, L<SHA384(3)>
and L<SHA512(3)> have changed to macros that use L<EVP_Q_digest(3)>.
=head4 Deprecated low-level signing functions
Use of low-level signing functions such as L<DSA_sign(3)> have been
informally discouraged for a long time. Instead applications should use
L<EVP_DigestSign(3)> and L<EVP_DigestVerify(3)>.
See also L<EVP_SIGNATURE-RSA(7)>, L<EVP_SIGNATURE-DSA(7)>,
L<EVP_SIGNATURE-ECDSA(7)> and L<EVP_SIGNATURE-ED25519(7)>.
=head4 Deprecated low-level MAC functions
Low-level mac functions such as L<CMAC_Init(3)> are deprecated.
Applications should instead use the new L<EVP_MAC(3)> interface, using
L<EVP_MAC_CTX_new(3)>, L<EVP_MAC_CTX_free(3)>, L<EVP_MAC_init(3)>,
L<EVP_MAC_update(3)> and L<EVP_MAC_final(3)> or the single-shot MAC function
L<EVP_Q_mac(3)>.
See L<EVP_MAC(3)>, L<EVP_MAC-HMAC(7)>, L<EVP_MAC-CMAC(7)>, L<EVP_MAC-GMAC(7)>,
L<EVP_MAC-KMAC(7)>, L<EVP_MAC-BLAKE2(7)>, L<EVP_MAC-Poly1305(7)> and
L<EVP_MAC-Siphash(7)> for additional information.
Note that the one-shot method HMAC() is still available for compatibility purposes,
but this can also be replaced by using EVP_Q_MAC if a library context is required.
=head4 Deprecated low-level validation functions
Low-level validation functions such as L<DH_check(3)> have been informally
discouraged from use for a long time. Applications should instead use the high-level
EVP_PKEY APIs such as L<EVP_PKEY_check(3)>, L<EVP_PKEY_param_check(3)>,
L<EVP_PKEY_param_check_quick(3)>, L<EVP_PKEY_public_check(3)>,
L<EVP_PKEY_public_check_quick(3)>, L<EVP_PKEY_private_check(3)>,
and L<EVP_PKEY_pairwise_check(3)>.
=head4 Deprecated low-level key exchange functions
Many low-level functions have been informally discouraged from use for a long
time. Applications should instead use L<EVP_PKEY_derive(3)>.
See L<EVP_KEYEXCH-DH(7)>, L<EVP_KEYEXCH-ECDH(7)> and L<EVP_KEYEXCH-X25519(7)>.
=head4 Deprecated low-level key generation functions
Many low-level functions have been informally discouraged from use for a long
time. Applications should instead use L<EVP_PKEY_keygen_init(3)> and
L<EVP_PKEY_generate(3)> as described in L<EVP_PKEY-DSA(7)>, L<EVP_PKEY-DH(7)>,
L<EVP_PKEY-RSA(7)>, L<EVP_PKEY-EC(7)> and L<EVP_PKEY-X25519(7)>.
The 'quick' one-shot function L<EVP_PKEY_Q_keygen(3)> and macros for the most
common cases: <EVP_RSA_gen(3)> and L<EVP_EC_gen(3)> may also be used.
=head4 Deprecated low-level key reading and writing functions
Use of low-level objects (such as DSA) has been informally discouraged from use
for a long time. Functions to read and write these low-level objects (such as
PEM_read_DSA_PUBKEY()) should be replaced. Applications should instead use
L<OSSL_ENCODER_to_bio(3)> and L<OSSL_DECODER_from_bio(3)>.
=head4 Deprecated low-level key printing functions
Use of low-level objects (such as DSA) has been informally discouraged from use
for a long time. Functions to print these low-level objects such as
DSA_print() should be replaced with the equivalent EVP_PKEY functions.
Application should use one of L<EVP_PKEY_print_public(3)>,
L<EVP_PKEY_print_private(3)>, L<EVP_PKEY_print_params(3)>,
L<EVP_PKEY_print_public_fp(3)>, L<EVP_PKEY_print_private_fp(3)> or
L<EVP_PKEY_print_params_fp(3)>. Note that internally these use
L<OSSL_ENCODER_to_bio(3)> and L<OSSL_DECODER_from_bio(3)>.
=head3 Deprecated function mappings
The following functions have been deprecated in 3.0.
=over 4
=item *
AES_bi_ige_encrypt() and AES_ige_encrypt()
There is no replacement for the IGE functions. New code should not use these modes.
These undocumented functions were never integrated into the EVP layer.
They implemented the AES Infinite Garble Extension (IGE) mode and AES
Bi-directional IGE mode. These modes were never formally standardised and
usage of these functions is believed to be very small. In particular
AES_bi_ige_encrypt() has a known bug. It accepts 2 AES keys, but only one
is ever used. The security implications are believed to be minimal, but
this issue was never fixed for backwards compatibility reasons.
=item *
AES_encrypt(), AES_decrypt(), AES_set_encrypt_key(), AES_set_decrypt_key(),
AES_cbc_encrypt(), AES_cfb128_encrypt(), AES_cfb1_encrypt(), AES_cfb8_encrypt(),
AES_ecb_encrypt(), AES_ofb128_encrypt()
=item *
AES_unwrap_key(), AES_wrap_key()
See L</Deprecated low-level encryption functions>
=item *
AES_options()
There is no replacement. It returned a string indicating if the AES code was unrolled.
=item *
ASN1_digest(), ASN1_sign(), ASN1_verify()
There are no replacements. These old functions are not used, and could be
disabled with the macro NO_ASN1_OLD since OpenSSL 0.9.7.
=item *
ASN1_STRING_length_set()
Use L<ASN1_STRING_set(3)> or L<ASN1_STRING_set0(3)> instead.
This was a potentially unsafe function that could change the bounds of a
previously passed in pointer.
=item *
BF_encrypt(), BF_decrypt(), BF_set_key(), BF_cbc_encrypt(), BF_cfb64_encrypt(),
BF_ecb_encrypt(), BF_ofb64_encrypt()
See L</Deprecated low-level encryption functions>.
The Blowfish algorithm has been moved to the L<Legacy Provider|/Legacy Algorithms>.
=item *
BF_options()
There is no replacement. This option returned a constant string.
=item *
BIO_get_callback(), BIO_set_callback(), BIO_debug_callback()
Use the respective non-deprecated _ex() functions.
=item *
BN_is_prime_ex(), BN_is_prime_fasttest_ex()
Use L<BN_check_prime(3)> which avoids possible misuse and always uses at least
64 rounds of the Miller-Rabin primality test.
=item *
BN_pseudo_rand(), BN_pseudo_rand_range()
Use L<BN_rand(3)> and L<BN_rand_range(3)>.
=item *
BN_X931_derive_prime_ex(), BN_X931_generate_prime_ex(), BN_X931_generate_Xpq()
There are no replacements for these low-level functions. They were used internally
by RSA_X931_derive_ex() and RSA_X931_generate_key_ex() which are also deprecated.
Use L<EVP_PKEY_keygen(3)> instead.
=item *
Camellia_encrypt(), Camellia_decrypt(), Camellia_set_key(),
Camellia_cbc_encrypt(), Camellia_cfb128_encrypt(), Camellia_cfb1_encrypt(),
Camellia_cfb8_encrypt(), Camellia_ctr128_encrypt(), Camellia_ecb_encrypt(),
Camellia_ofb128_encrypt()
See L</Deprecated low-level encryption functions>.
=item *
CAST_encrypt(), CAST_decrypt(), CAST_set_key(), CAST_cbc_encrypt(),
CAST_cfb64_encrypt(), CAST_ecb_encrypt(), CAST_ofb64_encrypt()
See L</Deprecated low-level encryption functions>.
The CAST algorithm has been moved to the L<Legacy Provider|/Legacy Algorithms>.
=item *
CMAC_CTX_new(), CMAC_CTX_cleanup(), CMAC_CTX_copy(), CMAC_CTX_free(),
CMAC_CTX_get0_cipher_ctx()
See L</Deprecated low-level MAC functions>.
=item *
CMAC_Init(), CMAC_Update(), CMAC_Final(), CMAC_resume()
See L</Deprecated low-level MAC functions>.
=item *
CRYPTO_mem_ctrl(), CRYPTO_mem_debug_free(), CRYPTO_mem_debug_malloc(),
CRYPTO_mem_debug_pop(), CRYPTO_mem_debug_push(), CRYPTO_mem_debug_realloc(),
CRYPTO_mem_leaks(), CRYPTO_mem_leaks_cb(), CRYPTO_mem_leaks_fp(),
CRYPTO_set_mem_debug()
Memory-leak checking has been deprecated in favor of more modern development
tools, such as compiler memory and leak sanitizers or Valgrind.
=item *
CRYPTO_cts128_encrypt_block(), CRYPTO_cts128_encrypt(),
CRYPTO_cts128_decrypt_block(), CRYPTO_cts128_decrypt(),
CRYPTO_nistcts128_encrypt_block(), CRYPTO_nistcts128_encrypt(),
CRYPTO_nistcts128_decrypt_block(), CRYPTO_nistcts128_decrypt()
Use the higher level functions EVP_CipherInit_ex2(), EVP_CipherUpdate() and
EVP_CipherFinal_ex() instead.
See the "cts_mode" parameter in
L<EVP_EncryptInit(3)/Gettable and Settable EVP_CIPHER_CTX parameters>.
See L<EVP_EncryptInit(3)/EXAMPLES> for a AES-256-CBC-CTS example.
=item *
d2i_DHparams(), d2i_DHxparams(), d2i_DSAparams(), d2i_DSAPrivateKey(),
d2i_DSAPrivateKey_bio(), d2i_DSAPrivateKey_fp(), d2i_DSA_PUBKEY(),
d2i_DSA_PUBKEY_bio(), d2i_DSA_PUBKEY_fp(), d2i_DSAPublicKey(),
d2i_ECParameters(), d2i_ECPrivateKey(), d2i_ECPrivateKey_bio(),
d2i_ECPrivateKey_fp(), d2i_EC_PUBKEY(), d2i_EC_PUBKEY_bio(),
d2i_EC_PUBKEY_fp(), o2i_ECPublicKey(), d2i_RSAPrivateKey(),
d2i_RSAPrivateKey_bio(), d2i_RSAPrivateKey_fp(), d2i_RSA_PUBKEY(),
d2i_RSA_PUBKEY_bio(), d2i_RSA_PUBKEY_fp(), d2i_RSAPublicKey(),
d2i_RSAPublicKey_bio(), d2i_RSAPublicKey_fp()
See L</Deprecated i2d and d2i functions for low-level key types>
=item *
DES_crypt(), DES_fcrypt(), DES_encrypt1(), DES_encrypt2(), DES_encrypt3(),
DES_decrypt3(), DES_ede3_cbc_encrypt(), DES_ede3_cfb64_encrypt(),
DES_ede3_cfb_encrypt(),DES_ede3_ofb64_encrypt(),
DES_ecb_encrypt(), DES_ecb3_encrypt(), DES_ofb64_encrypt(), DES_ofb_encrypt(),
DES_cfb64_encrypt DES_cfb_encrypt(), DES_cbc_encrypt(), DES_ncbc_encrypt(),
DES_pcbc_encrypt(), DES_xcbc_encrypt(), DES_cbc_cksum(), DES_quad_cksum(),
DES_check_key_parity(), DES_is_weak_key(), DES_key_sched(), DES_options(),
DES_random_key(), DES_set_key(), DES_set_key_checked(), DES_set_key_unchecked(),
DES_set_odd_parity(), DES_string_to_2keys(), DES_string_to_key()
See L</Deprecated low-level encryption functions>.
Algorithms for "DESX-CBC", "DES-ECB", "DES-CBC", "DES-OFB", "DES-CFB",
"DES-CFB1" and "DES-CFB8" have been moved to the L<Legacy Provider|/Legacy Algorithms>.
=item *
DH_bits(), DH_security_bits(), DH_size()
Use L<EVP_PKEY_get_bits(3)>, L<EVP_PKEY_get_security_bits(3)> and
L<EVP_PKEY_get_size(3)>.
=item *
DH_check(), DH_check_ex(), DH_check_params(), DH_check_params_ex(),
DH_check_pub_key(), DH_check_pub_key_ex()
See L</Deprecated low-level validation functions>
=item *
DH_clear_flags(), DH_test_flags(), DH_set_flags()
The B<DH_FLAG_CACHE_MONT_P> flag has been deprecated without replacement.
The B<DH_FLAG_TYPE_DH> and B<DH_FLAG_TYPE_DHX> have been deprecated.
Use EVP_PKEY_is_a() to determine the type of a key.
There is no replacement for setting these flags.
=item *
DH_compute_key() DH_compute_key_padded()
See L</Deprecated low-level key exchange functions>.
=item *
DH_new(), DH_new_by_nid(), DH_free(), DH_up_ref()
See L</Deprecated low-level object creation>
=item *
DH_generate_key(), DH_generate_parameters_ex()
See L</Deprecated low-level key generation functions>.
=item *
DH_get0_pqg(), DH_get0_p(), DH_get0_q(), DH_get0_g(), DH_get0_key(),
DH_get0_priv_key(), DH_get0_pub_key(), DH_get_length(), DH_get_nid()
See L</Deprecated low-level key parameter getters>
=item *
DH_get_1024_160(), DH_get_2048_224(), DH_get_2048_256()
Applications should instead set the B<OSSL_PKEY_PARAM_GROUP_NAME> as specified in
L<EVP_PKEY-DH(7)/DH parameters>) to one of "dh_1024_160", "dh_2048_224" or
"dh_2048_256" when generating a DH key.
=item *
DH_KDF_X9_42()
Applications should use L<EVP_PKEY_CTX_set_dh_kdf_type(3)> instead.
=item *
DH_get_default_method(), DH_get0_engine(), DH_meth_*(), DH_new_method(),
DH_OpenSSL(), DH_get_ex_data(), DH_set_default_method(), DH_set_method(),
DH_set_ex_data()
See L</Providers are a replacement for engines and low-level method overrides>
=item *
DHparams_print(), DHparams_print_fp()
See L</Deprecated low-level key printing functions>
=item *
DH_set0_key(), DH_set0_pqg(), DH_set_length()
See L</Deprecated low-level key parameter setters>
=item *
DSA_bits(), DSA_security_bits(), DSA_size()
Use L<EVP_PKEY_get_bits(3)>, L<EVP_PKEY_get_security_bits(3)> and
L<EVP_PKEY_get_size(3)>.
=item *
DHparams_dup(), DSA_dup_DH()
There is no direct replacement. Applications may use L<EVP_PKEY_copy_parameters(3)>
and L<EVP_PKEY_dup(3)> instead.
=item *
DSA_generate_key(), DSA_generate_parameters_ex()
See L</Deprecated low-level key generation functions>.
=item *
DSA_get0_engine(), DSA_get_default_method(), DSA_get_ex_data(),
DSA_get_method(), DSA_meth_*(), DSA_new_method(), DSA_OpenSSL(),
DSA_set_default_method(), DSA_set_ex_data(), DSA_set_method()
See L</Providers are a replacement for engines and low-level method overrides>.
=item *
DSA_get0_p(), DSA_get0_q(), DSA_get0_g(), DSA_get0_pqg(), DSA_get0_key(),
DSA_get0_priv_key(), DSA_get0_pub_key()
See L</Deprecated low-level key parameter getters>.
=item *
DSA_new(), DSA_free(), DSA_up_ref()
See L</Deprecated low-level object creation>
=item *
DSAparams_dup()
There is no direct replacement. Applications may use L<EVP_PKEY_copy_parameters(3)>
and L<EVP_PKEY_dup(3)> instead.
=item *
DSAparams_print(), DSAparams_print_fp(), DSA_print(), DSA_print_fp()
See L</Deprecated low-level key printing functions>
=item *
DSA_set0_key(), DSA_set0_pqg()
See L</Deprecated low-level key parameter setters>
=item *
DSA_set_flags(), DSA_clear_flags(), DSA_test_flags()
The B<DSA_FLAG_CACHE_MONT_P> flag has been deprecated without replacement.
=item *
DSA_sign(), DSA_do_sign(), DSA_sign_setup(), DSA_verify(), DSA_do_verify()
See L</Deprecated low-level signing functions>.
=item *
ECDH_compute_key()
See L</Deprecated low-level key exchange functions>.
=item *
ECDH_KDF_X9_62()
Applications may either set this using the helper function
L<EVP_PKEY_CTX_set_ecdh_kdf_type(3)> or by setting an L<OSSL_PARAM(3)> using the
"kdf-type" as shown in L<EVP_KEYEXCH-ECDH(7)/EXAMPLES>
=item *
ECDSA_sign(), ECDSA_sign_ex(), ECDSA_sign_setup(), ECDSA_do_sign(),
ECDSA_do_sign_ex(), ECDSA_verify(), ECDSA_do_verify()
See L</Deprecated low-level signing functions>.
=item *
ECDSA_size()
Applications should use L<EVP_PKEY_get_size(3)>.
=item *
EC_GF2m_simple_method(), EC_GFp_mont_method(), EC_GFp_nist_method(),
EC_GFp_nistp224_method(), EC_GFp_nistp256_method(), EC_GFp_nistp521_method(),
EC_GFp_simple_method()
There are no replacements for these functions. Applications should rely on the
library automatically assigning a suitable method internally when an EC_GROUP
is constructed.
=item *
EC_GROUP_clear_free()
Use L<EC_GROUP_free(3)> instead.
=item *
EC_GROUP_get_curve_GF2m(), EC_GROUP_get_curve_GFp(), EC_GROUP_set_curve_GF2m(),
EC_GROUP_set_curve_GFp()
Applications should use L<EC_GROUP_get_curve(3)> and L<EC_GROUP_set_curve(3)>.
=item *
EC_GROUP_have_precompute_mult(), EC_GROUP_precompute_mult(),
EC_KEY_precompute_mult()
These functions are not widely used. Applications should instead switch to
named curves which OpenSSL has hardcoded lookup tables for.
=item *
EC_GROUP_new(), EC_GROUP_method_of(), EC_POINT_method_of()
EC_METHOD is now an internal-only concept and a suitable EC_METHOD is assigned
internally without application intervention.
Users of EC_GROUP_new() should switch to a different suitable constructor.
=item *
EC_KEY_can_sign()
Applications should use L<EVP_PKEY_can_sign(3)> instead.
=item *
EC_KEY_check_key()
See L</Deprecated low-level validation functions>
=item *
EC_KEY_set_flags(), EC_KEY_get_flags(), EC_KEY_clear_flags()
See L<EVP_PKEY-EC(7)/Common EC parameters> which handles flags as seperate
parameters for B<OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT>,
B<OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE>, B<OSSL_PKEY_PARAM_EC_ENCODING>,
B<OSSL_PKEY_PARAM_USE_COFACTOR_ECDH> and
B<OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC>.
See also L<EVP_PKEY-EC(7)/EXAMPLES>
=item *
EC_KEY_dup(), EC_KEY_copy()
There is no direct replacement. Applications may use L<EVP_PKEY_copy_parameters(3)>
and L<EVP_PKEY_dup(3)> instead.
=item *
EC_KEY_decoded_from_explicit_params()
There is no replacement.
=item *
EC_KEY_generate_key()
See L</Deprecated low-level key generation functions>.
=item *
EC_KEY_get0_group(), EC_KEY_get0_private_key(), EC_KEY_get0_public_key(),
EC_KEY_get_conv_form(), EC_KEY_get_enc_flags()
See L</Deprecated low-level key parameter getters>.
=item *
EC_KEY_get0_engine(), EC_KEY_get_default_method(), EC_KEY_get_method(),
EC_KEY_new_method(), EC_KEY_get_ex_data(), EC_KEY_OpenSSL(),
EC_KEY_set_ex_data(), EC_KEY_set_default_method(), EC_KEY_METHOD_*(),
EC_KEY_set_method()
See L</Providers are a replacement for engines and low-level method overrides>
=item *
EC_METHOD_get_field_type()
Use L<EC_GROUP_get_field_type(3)> instead.
See L</Providers are a replacement for engines and low-level method overrides>
=item *
EC_KEY_key2buf(), EC_KEY_oct2key(), EC_KEY_oct2priv(), EC_KEY_priv2buf(),
EC_KEY_priv2oct()
There are no replacements for these.
=item *
EC_KEY_new(), EC_KEY_new_by_curve_name(), EC_KEY_free(), EC_KEY_up_ref()
See L</Deprecated low-level object creation>
=item *
EC_KEY_print(), EC_KEY_print_fp()
See L</Deprecated low-level key printing functions>
=item *
EC_KEY_set_asn1_flag(), EC_KEY_set_conv_form(), EC_KEY_set_enc_flags()
See L</Deprecated low-level key parameter setters>.
=item *
EC_KEY_set_group(), EC_KEY_set_private_key(), EC_KEY_set_public_key(),
EC_KEY_set_public_key_affine_coordinates()
See L</Deprecated low-level key parameter setters>.
=item *
ECParameters_print(), ECParameters_print_fp(), ECPKParameters_print(),
ECPKParameters_print_fp()
See L</Deprecated low-level key printing functions>
=item *
EC_POINT_bn2point(), EC_POINT_point2bn()
These functions were not particularly useful, since EC point serialization
formats are not individual big-endian integers.
=item *
EC_POINT_get_affine_coordinates_GF2m(), EC_POINT_get_affine_coordinates_GFp(),
EC_POINT_set_affine_coordinates_GF2m(), EC_POINT_set_affine_coordinates_GFp()
Applications should use L<EC_POINT_get_affine_coordinates(3)> and
L<EC_POINT_set_affine_coordinates(3)> instead.
=item *
EC_POINT_get_Jprojective_coordinates_GFp(), EC_POINT_set_Jprojective_coordinates_GFp()
These functions are not widely used. Applications should instead use the
L<EC_POINT_set_affine_coordinates(3)> and L<EC_POINT_get_affine_coordinates(3)>
functions.
=item *
EC_POINT_make_affine(), EC_POINTs_make_affine()
There is no replacement. These functions were not widely used, and OpenSSL
automatically performs this conversion when needed.
=item *
EC_POINT_set_compressed_coordinates_GF2m(), EC_POINT_set_compressed_coordinates_GFp()
Applications should use L<EC_POINT_set_compressed_coordinates(3)> instead.
=item *
EC_POINTs_mul()
This function is not widely used. Applications should instead use the
L<EC_POINT_mul(3)> function.
=item *
B<ENGINE_*()>
All engine functions are deprecated. An engine should be rewritten as a provider.
See L</Providers are a replacement for engines and low-level method overrides>.
=item *
B<ERR_load_*()>, ERR_func_error_string(), ERR_get_error_line(),
ERR_get_error_line_data(), ERR_get_state()
OpenSSL now loads error strings automatically so these functions are not needed.
=item *
ERR_peek_error_line_data(), ERR_peek_last_error_line_data()
The new functions are L<ERR_peek_error_func(3)>, L<ERR_peek_last_error_func(3)>,
L<ERR_peek_error_data(3)>, L<ERR_peek_last_error_data(3)>, L<ERR_get_error_all(3)>,
L<ERR_peek_error_all(3)> and L<ERR_peek_last_error_all(3)>.
Applications should use L<ERR_get_error_all(3)>, or pick information
with ERR_peek functions and finish off with getting the error code by using
L<ERR_get_error(3)>.
=item *
EVP_CIPHER_CTX_iv(), EVP_CIPHER_CTX_iv_noconst(), EVP_CIPHER_CTX_original_iv()
Applications should instead use L<EVP_CIPHER_CTX_get_updated_iv(3)>,
L<EVP_CIPHER_CTX_get_updated_iv(3)> and L<EVP_CIPHER_CTX_get_original_iv(3)>
respectively.
See L<EVP_CIPHER_CTX_get_original_iv(3)> for further information.
=item *
B<EVP_CIPHER_meth_*()>, EVP_MD_CTX_set_update_fn(), EVP_MD_CTX_update_fn(),
B<EVP_MD_meth_*()>
See L</Providers are a replacement for engines and low-level method overrides>.
=item *
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()
These control operations are not invoked by the OpenSSL library anymore and
are replaced by direct checks of the key operation against the key type
when the operation is initialized.
=item *
EVP_PKEY_CTX_get0_dh_kdf_ukm(), EVP_PKEY_CTX_get0_ecdh_kdf_ukm()
See the "kdf-ukm" item in L<EVP_KEYEXCH-DH(7)/DH key exchange parameters> and
L<EVP_KEYEXCH-ECDH(7)/ECDH Key Exchange parameters>.
These functions are obsolete and should not be required.
=item *
EVP_PKEY_CTX_set_rsa_keygen_pubexp()
Applications should use L<EVP_PKEY_CTX_set1_rsa_keygen_pubexp(3)> instead.
=item *
EVP_PKEY_cmp(), EVP_PKEY_cmp_parameters()
Applications should use L<EVP_PKEY_eq(3)> and L<EVP_PKEY_parameters_eq(3)> instead.
See L<EVP_PKEY_copy_parameters(3)> for further details.
=item *
EVP_PKEY_encrypt_old(), EVP_PKEY_decrypt_old(),
Applications should use L<EVP_PKEY_encrypt_init(3)> and L<EVP_PKEY_encrypt(3)> or
L<EVP_PKEY_decrypt_init(3)> and L<EVP_PKEY_decrypt(3)> instead.
=item *
EVP_PKEY_get0()
This function returns NULL if the key comes from a provider.
=item *
EVP_PKEY_get0_DH(), EVP_PKEY_get0_DSA(), EVP_PKEY_get0_EC_KEY(), EVP_PKEY_get0_RSA(),
EVP_PKEY_get1_DH(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_EC_KEY and EVP_PKEY_get1_RSA(),
EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305(), EVP_PKEY_get0_siphash()
See L</Functions that return an internal key should be treated as read only>.
=item *
B<EVP_PKEY_meth_*()>
See L</Providers are a replacement for engines and low-level method overrides>.
=item *
EVP_PKEY_new_CMAC_key()
See L</Deprecated low-level MAC functions>.
=item *
EVP_PKEY_assign(), EVP_PKEY_set1_DH(), EVP_PKEY_set1_DSA(),
EVP_PKEY_set1_EC_KEY(), EVP_PKEY_set1_RSA()
See L</Deprecated low-level key object getters and setters>
=item *
EVP_PKEY_set1_tls_encodedpoint() EVP_PKEY_get1_tls_encodedpoint()
These functions were previously used by libssl to set or get an encoded public
key into/from an EVP_PKEY object. With OpenSSL 3.0 these are replaced by the more
generic functions L<EVP_PKEY_set1_encoded_public_key(3)> and
L<EVP_PKEY_get1_encoded_public_key(3)>.
The old versions have been converted to deprecated macros that just call the
new functions.
=item *
EVP_PKEY_set1_engine(), EVP_PKEY_get0_engine()
See L</Providers are a replacement for engines and low-level method overrides>.
=item *
EVP_PKEY_set_alias_type()
This function has been removed. There is no replacement.
See L</EVP_PKEY_set_alias_type() method has been removed>
=item *
HMAC_Init_ex(), HMAC_Update(), HMAC_Final(), HMAC_size()
See L</Deprecated low-level MAC functions>.
=item *
HMAC_CTX_new(), HMAC_CTX_free(), HMAC_CTX_copy(), HMAC_CTX_reset(),
HMAC_CTX_set_flags(), HMAC_CTX_get_md()
See L</Deprecated low-level MAC functions>.
=item *
i2d_DHparams(), i2d_DHxparams()
See L</Deprecated low-level key reading and writing functions>
and L<d2i_RSAPrivateKey(3)/Migration>
=item *
i2d_DSAparams(), i2d_DSAPrivateKey(), i2d_DSAPrivateKey_bio(),
i2d_DSAPrivateKey_fp(), i2d_DSA_PUBKEY(), i2d_DSA_PUBKEY_bio(),
i2d_DSA_PUBKEY_fp(), i2d_DSAPublicKey()
See L</Deprecated low-level key reading and writing functions>
and L<d2i_RSAPrivateKey(3)/Migration>
=item *
i2d_ECParameters(), i2d_ECPrivateKey(), i2d_ECPrivateKey_bio(),
i2d_ECPrivateKey_fp(), i2d_EC_PUBKEY(), i2d_EC_PUBKEY_bio(),
i2d_EC_PUBKEY_fp(), i2o_ECPublicKey()
See L</Deprecated low-level key reading and writing functions>
and L<d2i_RSAPrivateKey(3)/Migration>
=item *
i2d_RSAPrivateKey(), i2d_RSAPrivateKey_bio(), i2d_RSAPrivateKey_fp(),
i2d_RSA_PUBKEY(), i2d_RSA_PUBKEY_bio(), i2d_RSA_PUBKEY_fp(),
i2d_RSAPublicKey(), i2d_RSAPublicKey_bio(), i2d_RSAPublicKey_fp()
See L</Deprecated low-level key reading and writing functions>
and L<d2i_RSAPrivateKey(3)/Migration>
=item *
IDEA_encrypt(), IDEA_set_decrypt_key(), IDEA_set_encrypt_key(),
IDEA_cbc_encrypt(), IDEA_cfb64_encrypt(), IDEA_ecb_encrypt(),
IDEA_ofb64_encrypt()
See L</Deprecated low-level encryption functions>.
IDEA has been moved to the L<Legacy Provider|/Legacy Algorithms>.
=item *
IDEA_options()
There is no replacement. This function returned a constant string.
=item *
MD2(), MD2_Init(), MD2_Update(), MD2_Final()
See L</Deprecated low-level encryption functions>.
MD2 has been moved to the L<Legacy Provider|/Legacy Algorithms>.
=item *
MD2_options()
There is no replacement. This function returned a constant string.
=item *
MD4(), MD4_Init(), MD4_Update(), MD4_Final(), MD4_Transform()
See L</Deprecated low-level encryption functions>.
MD4 has been moved to the L<Legacy Provider|/Legacy Algorithms>.
=item *
MDC2(), MDC2_Init(), MDC2_Update(), MDC2_Final()
See L</Deprecated low-level encryption functions>.
MDC2 has been moved to the L<Legacy Provider|/Legacy Algorithms>.
=item *
MD5(), MD5_Init(), MD5_Update(), MD5_Final(), MD5_Transform()
See L</Deprecated low-level encryption functions>.
=item *
NCONF_WIN32()
This undocumented function has no replacement.
See L<config(5)/HISTORY> for more details.
=item *
OCSP_parse_url()
Use L<OSSL_HTTP_parse_url(3)> instead.
=item *
B<OCSP_REQ_CTX> type and B<OCSP_REQ_CTX_*()> functions
These methods were used to collect all necessary data to form a HTTP request,
and to perform the HTTP transfer with that request. With OpenSSL 3.0, the
type is B<OSSL_HTTP_REQ_CTX>, and the deprecated functions are replaced
with B<OSSL_HTTP_REQ_CTX_*()>. See L<OSSL_HTTP_REQ_CTX(3)> for additional
details.
=item *
OPENSSL_fork_child(), OPENSSL_fork_parent(), OPENSSL_fork_prepare()
There is no replacement for these functions. These pthread fork support methods
were unused by OpenSSL.
=item *
OSSL_STORE_ctrl(), OSSL_STORE_do_all_loaders(), OSSL_STORE_LOADER_get0_engine(),
OSSL_STORE_LOADER_get0_scheme(), OSSL_STORE_LOADER_new(),
OSSL_STORE_LOADER_set_attach(), OSSL_STORE_LOADER_set_close(),
OSSL_STORE_LOADER_set_ctrl(), OSSL_STORE_LOADER_set_eof(),
OSSL_STORE_LOADER_set_error(), OSSL_STORE_LOADER_set_expect(),
OSSL_STORE_LOADER_set_find(), OSSL_STORE_LOADER_set_load(),
OSSL_STORE_LOADER_set_open(), OSSL_STORE_LOADER_set_open_ex(),
OSSL_STORE_register_loader(), OSSL_STORE_unregister_loader(),
OSSL_STORE_vctrl()
These functions helped applications and engines create loaders for
schemes they supported. These are all deprecated and discouraged in favour of
provider implementations, see L<provider-storemgmt(7)>.
=item *
PEM_read_DHparams(), PEM_read_bio_DHparams(),
PEM_read_DSAparams(), PEM_read_bio_DSAparams(),
PEM_read_DSAPrivateKey(), PEM_read_DSA_PUBKEY(),
PEM_read_bio_DSAPrivateKey and PEM_read_bio_DSA_PUBKEY(),
PEM_read_ECPKParameters(), PEM_read_ECPrivateKey(), PEM_read_EC_PUBKEY(),
PEM_read_bio_ECPKParameters(), PEM_read_bio_ECPrivateKey(), PEM_read_bio_EC_PUBKEY(),
PEM_read_RSAPrivateKey(), PEM_read_RSA_PUBKEY(), PEM_read_RSAPublicKey(),
PEM_read_bio_RSAPrivateKey(), PEM_read_bio_RSA_PUBKEY(), PEM_read_bio_RSAPublicKey(),
PEM_write_bio_DHparams(), PEM_write_bio_DHxparams(), PEM_write_DHparams(), PEM_write_DHxparams(),
PEM_write_DSAparams(), PEM_write_DSAPrivateKey(), PEM_write_DSA_PUBKEY(),
PEM_write_bio_DSAparams(), PEM_write_bio_DSAPrivateKey(), PEM_write_bio_DSA_PUBKEY(),
PEM_write_ECPKParameters(), PEM_write_ECPrivateKey(), PEM_write_EC_PUBKEY(),
PEM_write_bio_ECPKParameters(), PEM_write_bio_ECPrivateKey(), PEM_write_bio_EC_PUBKEY(),
PEM_write_RSAPrivateKey(), PEM_write_RSA_PUBKEY(), PEM_write_RSAPublicKey(),
PEM_write_bio_RSAPrivateKey(), PEM_write_bio_RSA_PUBKEY(),
PEM_write_bio_RSAPublicKey(),
See L</Deprecated low-level key reading and writing functions>
=item *
PKCS1_MGF1()
See L</Deprecated low-level encryption functions>.
=item *
RAND_get_rand_method(), RAND_set_rand_method(), RAND_OpenSSL(),
RAND_set_rand_engine()
Applications should instead use L<RAND_set_DRBG_type(3)>,
L<EVP_RAND(3)> and L<EVP_RAND(7)>.
See L<RAND_set_rand_method(3)> for more details.
=item *
RC2_encrypt(), RC2_decrypt(), RC2_set_key(), RC2_cbc_encrypt(), RC2_cfb64_encrypt(),
RC2_ecb_encrypt(), RC2_ofb64_encrypt(),
RC4(), RC4_set_key(), RC4_options(),
RC5_32_encrypt(), RC5_32_set_key(), RC5_32_decrypt(), RC5_32_cbc_encrypt(),
RC5_32_cfb64_encrypt(), RC5_32_ecb_encrypt(), RC5_32_ofb64_encrypt()
See L</Deprecated low-level encryption functions>.
The Algorithms "RC2", "RC4" and "RC5" have been moved to the L<Legacy Provider|/Legacy Algorithms>.
=item *
RIPEMD160(), RIPEMD160_Init(), RIPEMD160_Update(), RIPEMD160_Final(),
RIPEMD160_Transform()
See L</Deprecated low-level digest functions>.
The RIPE algorithm has been moved to the L<Legacy Provider|/Legacy Algorithms>.
=item *
RSA_bits(), RSA_security_bits(), RSA_size()
Use L<EVP_PKEY_get_bits(3)>, L<EVP_PKEY_get_security_bits(3)> and
L<EVP_PKEY_get_size(3)>.
=item *
RSA_check_key(), RSA_check_key_ex()
See L</Deprecated low-level validation functions>
=item *
RSA_clear_flags(), RSA_flags(), RSA_set_flags(), RSA_test_flags(),
RSA_setup_blinding(), RSA_blinding_off(), RSA_blinding_on()
All of these RSA flags have been deprecated without replacement:
B<RSA_FLAG_BLINDING>, B<RSA_FLAG_CACHE_PRIVATE>, B<RSA_FLAG_CACHE_PUBLIC>,
B<RSA_FLAG_EXT_PKEY>, B<RSA_FLAG_NO_BLINDING>, B<RSA_FLAG_THREAD_SAFE>
B<RSA_METHOD_FLAG_NO_CHECK>
=item *
RSA_generate_key_ex(), RSA_generate_multi_prime_key()
See L</Deprecated low-level key generation functions>.
=item *
RSA_get0_engine()
See L</Providers are a replacement for engines and low-level method overrides>
=item *
RSA_get0_crt_params(), RSA_get0_d(), RSA_get0_dmp1(), RSA_get0_dmq1(),
RSA_get0_e(), RSA_get0_factors(), RSA_get0_iqmp(), RSA_get0_key(),
RSA_get0_multi_prime_crt_params(), RSA_get0_multi_prime_factors(), RSA_get0_n(),
RSA_get0_p(), RSA_get0_pss_params(), RSA_get0_q(),
RSA_get_multi_prime_extra_count()
See L</Deprecated low-level key parameter getters>
=item *
RSA_new(), RSA_free(), RSA_up_ref()
See L</Deprecated low-level object creation>.
=item *
RSA_get_default_method(), RSA_get_ex_data and RSA_get_method()
See L</Providers are a replacement for engines and low-level method overrides>.
=item *
RSA_get_version()
There is no replacement.
=item *
B<RSA_meth_*()>, RSA_new_method(), RSA_null_method and RSA_PKCS1_OpenSSL()
See L</Providers are a replacement for engines and low-level method overrides>.
=item *
B<RSA_padding_add_*()>, B<RSA_padding_check_*()>
See L</Deprecated low-level signing functions> and
L</Deprecated low-level encryption functions>.
=item *
RSA_print(), RSA_print_fp()
See L</Deprecated low-level key printing functions>
=item *
RSA_public_encrypt(), RSA_private_decrypt()
See L</Deprecated low-level encryption functions>
=item *
RSA_private_encrypt(), RSA_public_decrypt()
This is equivalent to doing sign and verify recover operations (with a padding
mode of none). See L</Deprecated low-level signing functions>.
=item *
RSAPrivateKey_dup(), RSAPublicKey_dup()
There is no direct replacement. Applications may use L<EVP_PKEY_dup(3)>.
=item *
RSAPublicKey_it(), RSAPrivateKey_it()
See L</Deprecated low-level key reading and writing functions>
=item *
RSA_set0_crt_params(), RSA_set0_factors(), RSA_set0_key(),
RSA_set0_multi_prime_params()
See L</Deprecated low-level key parameter setters>.
=item *
RSA_set_default_method(), RSA_set_method(), RSA_set_ex_data()
See L</Providers are a replacement for engines and low-level method overrides>
=item *
RSA_sign(), RSA_sign_ASN1_OCTET_STRING(), RSA_verify(),
RSA_verify_ASN1_OCTET_STRING(), RSA_verify_PKCS1_PSS(),
RSA_verify_PKCS1_PSS_mgf1()
See L</Deprecated low-level signing functions>.
=item *
RSA_X931_derive_ex(), RSA_X931_generate_key_ex(), RSA_X931_hash_id()
There are no replacements for these functions.
X931 padding can be set using L<EVP_SIGNATURE-RSA(7)/Signature Parameters>.
See B<OSSL_SIGNATURE_PARAM_PAD_MODE>.
=item *
SEED_encrypt(), SEED_decrypt(), SEED_set_key(), SEED_cbc_encrypt(),
SEED_cfb128_encrypt(), SEED_ecb_encrypt(), SEED_ofb128_encrypt()
See L</Deprecated low-level encryption functions>.
The SEED algorithm has been moved to the L<Legacy Provider|/Legacy Algorithms>.
=item *
SHA1_Init(), SHA1_Update(), SHA1_Final(), SHA1_Transform(),
SHA224_Init(), SHA224_Update(), SHA224_Final(),
SHA256_Init(), SHA256_Update(), SHA256_Final(), SHA256_Transform(),
SHA384_Init(), SHA384_Update(), SHA384_Final(),
SHA512_Init(), SHA512_Update(), SHA512_Final(), SHA512_Transform()
See L</Deprecated low-level digest functions>.
=item *
SRP_Calc_A(), SRP_Calc_B(), SRP_Calc_client_key(), SRP_Calc_server_key(),
SRP_Calc_u(), SRP_Calc_x(), SRP_check_known_gN_param(), SRP_create_verifier(),
SRP_create_verifier_BN(), SRP_get_default_gN(), SRP_user_pwd_free(), SRP_user_pwd_new(),
SRP_user_pwd_set0_sv(), SRP_user_pwd_set1_ids(), SRP_user_pwd_set_gN(),
SRP_VBASE_add0_user(), SRP_VBASE_free(), SRP_VBASE_get1_by_user(), SRP_VBASE_init(),
SRP_VBASE_new(), SRP_Verify_A_mod_N(), SRP_Verify_B_mod_N()
There are no replacements for the SRP functions.
=item *
SSL_CTX_set_tmp_dh_callback(), SSL_set_tmp_dh_callback(),
SSL_CTX_set_tmp_dh(), SSL_set_tmp_dh()
These are used to set the Diffie-Hellman (DH) parameters that are to be used by
servers requiring ephemeral DH keys. Instead applications should consider using
the built-in DH parameters that are available by calling L<SSL_CTX_set_dh_auto(3)>
or L<SSL_set_dh_auto(3)>. If custom parameters are necessary then applications can
use the alternative functions L<SSL_CTX_set0_tmp_dh_pkey(3)> and
L<SSL_set0_tmp_dh_pkey(3)>. There is no direct replacement for the "callback"
functions. The callback was originally useful in order to have different
parameters for export and non-export ciphersuites. Export ciphersuites are no
longer supported by OpenSSL. Use of the callback functions should be replaced
by one of the other methods described above.
=item *
SSL_CTX_set_tlsext_ticket_key_cb()
Use the new L<SSL_CTX_set_tlsext_ticket_key_evp_cb(3)> function instead.
=item *
WHIRLPOOL(), WHIRLPOOL_Init(), WHIRLPOOL_Update(), WHIRLPOOL_Final(),
WHIRLPOOL_BitUpdate()
See L</Deprecated low-level digest functions>.
The Whirlpool algorithm has been moved to the L<Legacy Provider|/Legacy Algorithms>.
=item *
X509_certificate_type()
This was an undocumented function. Applications can use L<X509_get0_pubkey(3)>
and L<X509_get0_signature(3)> instead.
=item *
X509_http_nbio(), X509_CRL_http_nbio()
Use L<X509_load_http(3)> and L<X509_CRL_load_http(3)> instead.
=back
+=head3 NID handling for provided keys and algorithms
+
+The following functions for NID (numeric id) handling have changed semantics.
+
+=over 4
+
+=item *
+
+EVP_PKEY_id(), EVP_PKEY_get_id()
+
+This function was previously used to reliably return the NID of
+an EVP_PKEY object, e.g., to look up the name of the algorithm of
+such EVP_PKEY by calling L<OBJ_nid2sn(3)>. With the introduction
+of L<provider(7)>s EVP_PKEY_id() or its new equivalent
+L<EVP_PKEY_get_id(3)> might now also return the value -1
+(B<EVP_PKEY_KEYMGMT>) indicating the use of a provider to
+implement the EVP_PKEY object. Therefore, the use of
+L<EVP_PKEY_get0_type_name(3)> is recommended for retrieving
+the name of the EVP_PKEY algorithm.
+
+=back
+
=head2 Using the FIPS Module in applications
See L<fips_module(7)> and L<OSSL_PROVIDER-FIPS(7)> for details.
=head2 OpenSSL command line application changes
=head3 New applications
L<B<openssl kdf>|openssl-kdf(1)> uses the new L<EVP_KDF(3)> API.
L<B<openssl kdf>|openssl-mac(1)> uses the new L<EVP_MAC(3)> API.
=head3 Added options
B<-provider_path> and B<-provider> are available to all apps and can be used
multiple times to load any providers, such as the 'legacy' provider or third
party providers. If used then the 'default' provider would also need to be
specified if required. The B<-provider_path> must be specified before the
B<-provider> option.
The B<list> app has many new options. See L<openssl-list(1)> for more
information.
B<-crl_lastupdate> and B<-crl_nextupdate> used by B<openssl ca> allows
explicit setting of fields in the generated CRL.
=head3 Removed options
Interactive mode is not longer available.
The B<-crypt> option used by B<openssl passwd>.
The B<-c> option used by B<openssl x509>, B<openssl dhparam>,
B<openssl dsaparam>, and B<openssl ecparam>.
=head3 Other Changes
The output of Command line applications may have minor changes.
These are primarily changes in capitalisation and white space. However, in some
cases, there are additional differences.
For example, the DH parameters output from B<openssl dhparam> now lists 'P',
'Q', 'G' and 'pcounter' instead of 'prime', 'generator', 'subgroup order' and
'counter' respectively.
The B<openssl> commands that read keys, certificates, and CRLs now
automatically detect the PEM or DER format of the input files so it is not
necessary to explicitly specify the input format anymore. However if the
input format option is used the specified format will be required.
B<openssl speed> no longer uses low-level API calls.
This implies some of the performance numbers might not be comparable with the
previous releases due to higher overhead. This applies particularly to
measuring performance on smaller data chunks.
b<openssl dhparam>, B<openssl dsa>, B<openssl gendsa>, B<openssl dsaparam>,
B<openssl genrsa> and B<openssl rsa> have been modified to use PKEY APIs.
B<openssl genrsa> and B<openssl rsa> now write PKCS #8 keys by default.
=head3 Default settings
"SHA256" is now the default digest for TS query used by B<openssl ts>.
=head3 Deprecated apps
B<openssl rsautl> is deprecated, use B<openssl pkeyutl> instead.
B<openssl dhparam>, B<openssl dsa>, B<openssl gendsa>, B<openssl dsaparam>,
B<openssl genrsa>, B<openssl rsa>, B<openssl genrsa> and B<openssl rsa> are
now in maintenance mode and no new features will be added to them.
=head2 TLS Changes
=over 4
=item *
TLS 1.3 FFDHE key exchange support added
This uses DH safe prime named groups.
=item *
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.
=item *
SSL and SSL_CTX options are now 64 bit instead of 32 bit.
The signatures of the functions to get and set options on SSL and
SSL_CTX objects changed from "unsigned long" to "uint64_t" type.
This may require source code changes. For example it is no longer possible
to use the B<SSL_OP_> macro values in preprocessor C<#if> conditions.
However it is still possible to test whether these macros are defined or not.
See L<SSL_CTX_get_options(3)>, L<SSL_CTX_set_options(3)>,
L<SSL_get_options(3)> and L<SSL_set_options(3)>.
=item *
SSL_set1_host() and SSL_add1_host() Changes
These functions now take IP literal addresses as well as actual hostnames.
=item *
Added SSL option SSL_OP_CLEANSE_PLAINTEXT
If the option is set, openssl cleanses (zeroizes) plaintext bytes from
internal buffers after delivering them to the application. Note,
the application is still responsible for cleansing other copies
(e.g.: data received by L<SSL_read(3)>).
=item *
Client-initiated renegotiation is disabled by default.
To allow it, use the B<-client_renegotiation> option,
the B<SSL_OP_ALLOW_CLIENT_RENEGOTIATION> flag, or the C<ClientRenegotiation>
config parameter as appropriate.
=item *
Secure renegotiation is now required by default for TLS connections
Support for RFC 5746 secure renegotiation is now required by default for
SSL or TLS connections to succeed. Applications that require the ability
to connect to legacy peers will need to explicitly set
SSL_OP_LEGACY_SERVER_CONNECT. Accordingly, SSL_OP_LEGACY_SERVER_CONNECT
is no longer set as part of SSL_OP_ALL.
=item *
Combining the Configure options no-ec and no-dh no longer disables TLSv1.3
Typically if OpenSSL has no EC or DH algorithms then it cannot support
connections with TLSv1.3. However OpenSSL now supports "pluggable" groups
through providers. Therefore third party providers may supply group
implementations even where there are no built-in ones. Attempting to create
TLS connections in such a build without also disabling TLSv1.3 at run time or
using third party provider groups may result in handshake failures. TLSv1.3
can be disabled at compile time using the "no-tls1_3" Configure option.
=item *
SSL_CTX_set_ciphersuites() and SSL_set_ciphersuites() changes.
The methods now ignore unknown ciphers.
=item *
Security callback change.
The security callback, which can be customised by application code, supports
the security operation SSL_SECOP_TMP_DH. This is defined to take an EVP_PKEY
in the "other" parameter. In most places this is what is passed. All these
places occur server side. However there was one client side call of this
security operation and it passed a DH object instead. This is incorrect
according to the definition of SSL_SECOP_TMP_DH, and is inconsistent with all
of the other locations. Therefore this client side call has been changed to
pass an EVP_PKEY instead.
=item *
New SSL option SSL_OP_IGNORE_UNEXPECTED_EOF
The SSL option SSL_OP_IGNORE_UNEXPECTED_EOF is introduced. If that option
is set, an unexpected EOF is ignored, it pretends a close notify was received
instead and so the returned error becomes SSL_ERROR_ZERO_RETURN.
=item *
The security strength of SHA1 and MD5 based signatures in TLS has been reduced.
This results in SSL 3, TLS 1.0, TLS 1.1 and DTLS 1.0 no longer
working at the default security level of 1 and instead requires security
level 0. The security level can be changed either using the cipher string
with C<@SECLEVEL>, or calling L<SSL_CTX_set_security_level(3)>. This also means
that where the signature algorithms extension is missing from a ClientHello
then the handshake will fail in TLS 1.2 at security level 1. This is because,
although this extension is optional, failing to provide one means that
OpenSSL will fallback to a default set of signature algorithms. This default
set requires the availability of SHA1.
=item *
X509 certificates signed using SHA1 are no longer allowed at security level 1 and above.
In TLS/SSL the default security level is 1. It can be set either using the cipher
string with C<@SECLEVEL>, or calling L<SSL_CTX_set_security_level(3)>. If the
leaf certificate is signed with SHA-1, a call to L<SSL_CTX_use_certificate(3)>
will fail if the security level is not lowered first.
Outside TLS/SSL, the default security level is -1 (effectively 0). It can
be set using L<X509_VERIFY_PARAM_set_auth_level(3)> or using the B<-auth_level>
options of the commands.
=back
=head1 SEE ALSO
L<fips_module(7)>
=head1 HISTORY
The migration guide was created for OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2021-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/doc/man7/provider-asym_cipher.pod b/doc/man7/provider-asym_cipher.pod
index ac3f6271969d..0976a263a883 100644
--- a/doc/man7/provider-asym_cipher.pod
+++ b/doc/man7/provider-asym_cipher.pod
@@ -1,269 +1,268 @@
=pod
=head1 NAME
provider-asym_cipher - The asym_cipher library E<lt>-E<gt> provider functions
=head1 SYNOPSIS
=for openssl multiple includes
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
/*
* None of these are actual functions, but are displayed like this for
* the function signatures for functions that are offered as function
* pointers in OSSL_DISPATCH arrays.
*/
/* Context management */
void *OSSL_FUNC_asym_cipher_newctx(void *provctx);
void OSSL_FUNC_asym_cipher_freectx(void *ctx);
void *OSSL_FUNC_asym_cipher_dupctx(void *ctx);
/* Encryption */
int OSSL_FUNC_asym_cipher_encrypt_init(void *ctx, void *provkey,
const OSSL_PARAM params[]);
int OSSL_FUNC_asym_cipher_encrypt(void *ctx, unsigned char *out, size_t *outlen,
size_t outsize, const unsigned char *in,
size_t inlen);
/* Decryption */
int OSSL_FUNC_asym_cipher_decrypt_init(void *ctx, void *provkey,
const OSSL_PARAM params[]);
int OSSL_FUNC_asym_cipher_decrypt(void *ctx, unsigned char *out, size_t *outlen,
size_t outsize, const unsigned char *in,
size_t inlen);
/* Asymmetric Cipher parameters */
int OSSL_FUNC_asym_cipher_get_ctx_params(void *ctx, OSSL_PARAM params[]);
const OSSL_PARAM *OSSL_FUNC_asym_cipher_gettable_ctx_params(void *provctx);
int OSSL_FUNC_asym_cipher_set_ctx_params(void *ctx, const OSSL_PARAM params[]);
const OSSL_PARAM *OSSL_FUNC_asym_cipher_settable_ctx_params(void *provctx);
=head1 DESCRIPTION
This documentation is primarily aimed at provider authors. See L<provider(7)>
for further information.
The asymmetric cipher (OSSL_OP_ASYM_CIPHER) operation enables providers to
implement asymmetric cipher algorithms and make them available to applications
via the API functions L<EVP_PKEY_encrypt(3)>,
L<EVP_PKEY_decrypt(3)> and
other related functions).
All "functions" mentioned here are passed as function pointers between
F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
provider_query_operation() function
(see L<provider-base(7)/Provider Functions>).
All these "functions" have a corresponding function type definition
named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
function pointer from an L<OSSL_DISPATCH(3)> element named
B<OSSL_FUNC_{name}>.
For example, the "function" OSSL_FUNC_asym_cipher_newctx() has these:
typedef void *(OSSL_FUNC_asym_cipher_newctx_fn)(void *provctx);
static ossl_inline OSSL_FUNC_asym_cipher_newctx_fn
OSSL_FUNC_asym_cipher_newctx(const OSSL_DISPATCH *opf);
L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
macros in L<openssl-core_dispatch.h(7)>, as follows:
OSSL_FUNC_asym_cipher_newctx OSSL_FUNC_ASYM_CIPHER_NEWCTX
OSSL_FUNC_asym_cipher_freectx OSSL_FUNC_ASYM_CIPHER_FREECTX
OSSL_FUNC_asym_cipher_dupctx OSSL_FUNC_ASYM_CIPHER_DUPCTX
OSSL_FUNC_asym_cipher_encrypt_init OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT
OSSL_FUNC_asym_cipher_encrypt OSSL_FUNC_ASYM_CIPHER_ENCRYPT
OSSL_FUNC_asym_cipher_decrypt_init OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT
OSSL_FUNC_asym_cipher_decrypt OSSL_FUNC_ASYM_CIPHER_DECRYPT
OSSL_FUNC_asym_cipher_get_ctx_params OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS
OSSL_FUNC_asym_cipher_gettable_ctx_params OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS
OSSL_FUNC_asym_cipher_set_ctx_params OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS
OSSL_FUNC_asym_cipher_settable_ctx_params OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS
An asymmetric cipher algorithm implementation may not implement all of these
functions.
In order to be a consistent set of functions a provider must implement
OSSL_FUNC_asym_cipher_newctx and OSSL_FUNC_asym_cipher_freectx.
It must also implement both of OSSL_FUNC_asym_cipher_encrypt_init and
OSSL_FUNC_asym_cipher_encrypt, or both of OSSL_FUNC_asym_cipher_decrypt_init and
OSSL_FUNC_asym_cipher_decrypt.
OSSL_FUNC_asym_cipher_get_ctx_params is optional but if it is present then so must
OSSL_FUNC_asym_cipher_gettable_ctx_params.
Similarly, OSSL_FUNC_asym_cipher_set_ctx_params is optional but if it is present then
so must OSSL_FUNC_asym_cipher_settable_ctx_params.
An asymmetric cipher algorithm must also implement some mechanism for generating,
loading or importing keys via the key management (OSSL_OP_KEYMGMT) operation.
See L<provider-keymgmt(7)> for further details.
=head2 Context Management Functions
OSSL_FUNC_asym_cipher_newctx() should create and return a pointer to a provider side
structure for holding context information during an asymmetric cipher operation.
A pointer to this context will be passed back in a number of the other
asymmetric cipher operation function calls.
The parameter I<provctx> is the provider context generated during provider
initialisation (see L<provider(7)>).
OSSL_FUNC_asym_cipher_freectx() is passed a pointer to the provider side asymmetric
cipher context in the I<ctx> parameter.
This function should free any resources associated with that context.
OSSL_FUNC_asym_cipher_dupctx() should duplicate the provider side asymmetric cipher
context in the I<ctx> parameter and return the duplicate copy.
=head2 Encryption Functions
OSSL_FUNC_asym_cipher_encrypt_init() initialises a context for an asymmetric encryption
given a provider side asymmetric cipher context in the I<ctx> parameter, and a
pointer to a provider key object in the I<provkey> parameter.
The I<params>, if not NULL, should be set on the context in a manner similar to
using OSSL_FUNC_asym_cipher_set_ctx_params().
The key object should have been previously generated, loaded or imported into
-the provider using the key management (OSSL_OP_KEYMGMT) operation (see
-provider-keymgmt(7)>.
+the provider using the key management (OSSL_OP_KEYMGMT) operation (see L<provider-keymgmt(7)>).
OSSL_FUNC_asym_cipher_encrypt() performs the actual encryption itself.
A previously initialised asymmetric cipher context is passed in the I<ctx>
parameter.
The data to be encrypted is pointed to by the I<in> parameter which is I<inlen>
bytes long.
Unless I<out> is NULL, the encrypted data should be written to the location
pointed to by the I<out> parameter and it should not exceed I<outsize> bytes in
length.
The length of the encrypted data should be written to I<*outlen>.
If I<out> is NULL then the maximum length of the encrypted data should be
written to I<*outlen>.
=head2 Decryption Functions
OSSL_FUNC_asym_cipher_decrypt_init() initialises a context for an asymmetric decryption
given a provider side asymmetric cipher context in the I<ctx> parameter, and a
pointer to a provider key object in the I<provkey> parameter.
The I<params>, if not NULL, should be set on the context in a manner similar to
using OSSL_FUNC_asym_cipher_set_ctx_params().
The key object should have been previously generated, loaded or imported into
the provider using the key management (OSSL_OP_KEYMGMT) operation (see
-provider-keymgmt(7)>.
+L<provider-keymgmt(7)>).
OSSL_FUNC_asym_cipher_decrypt() performs the actual decryption itself.
A previously initialised asymmetric cipher context is passed in the I<ctx>
parameter.
The data to be decrypted is pointed to by the I<in> parameter which is I<inlen>
bytes long.
Unless I<out> is NULL, the decrypted data should be written to the location
pointed to by the I<out> parameter and it should not exceed I<outsize> bytes in
length.
The length of the decrypted data should be written to I<*outlen>.
If I<out> is NULL then the maximum length of the decrypted data should be
written to I<*outlen>.
=head2 Asymmetric Cipher Parameters
See L<OSSL_PARAM(3)> for further details on the parameters structure used by
the OSSL_FUNC_asym_cipher_get_ctx_params() and OSSL_FUNC_asym_cipher_set_ctx_params()
functions.
OSSL_FUNC_asym_cipher_get_ctx_params() gets asymmetric cipher parameters associated
with the given provider side asymmetric cipher context I<ctx> and stores them in
I<params>.
Passing NULL for I<params> should return true.
OSSL_FUNC_asym_cipher_set_ctx_params() sets the asymmetric cipher parameters associated
with the given provider side asymmetric cipher context I<ctx> to I<params>.
Any parameter settings are additional to any that were previously set.
Passing NULL for I<params> should return true.
Parameters currently recognised by built-in asymmetric cipher algorithms are as
follows.
Not all parameters are relevant to, or are understood by all asymmetric cipher
algorithms:
=over 4
=item "pad-mode" (B<OSSL_ASYM_CIPHER_PARAM_PAD_MODE>) <UTF8 string> OR <integer>
The type of padding to be used. The interpretation of this value will depend
on the algorithm in use.
=item "digest" (B<OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST>) <UTF8 string>
Gets or sets the name of the OAEP digest algorithm used when OAEP padding is in
use.
=item "digest" (B<OSSL_ASYM_CIPHER_PARAM_DIGEST>) <UTF8 string>
Gets or sets the name of the digest algorithm used by the algorithm (where
applicable).
=item "digest-props" (B<OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS>) <UTF8 string>
Gets or sets the properties to use when fetching the OAEP digest algorithm.
=item "digest-props" (B<OSSL_ASYM_CIPHER_PARAM_DIGEST_PROPS>) <UTF8 string>
Gets or sets the properties to use when fetching the cipher digest algorithm.
=item "mgf1-digest" (B<OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST>) <UTF8 string>
Gets or sets the name of the MGF1 digest algorithm used when OAEP or PSS padding
is in use.
=item "mgf1-digest-props" (B<OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS>) <UTF8 string>
Gets or sets the properties to use when fetching the MGF1 digest algorithm.
=item "oaep-label" (B<OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL>) <octet string ptr>
Gets the OAEP label used when OAEP padding is in use.
=item "oaep-label" (B<OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL>) <octet string>
Sets the OAEP label used when OAEP padding is in use.
=item "tls-client-version" (B<OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION>) <unsigned integer>
The TLS protocol version first requested by the client.
=item "tls-negotiated-version" (B<OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION>) <unsigned integer>
The negotiated TLS protocol version.
=back
OSSL_FUNC_asym_cipher_gettable_ctx_params() and OSSL_FUNC_asym_cipher_settable_ctx_params()
get a constant L<OSSL_PARAM(3)> array that describes the gettable and settable
parameters, i.e. parameters that can be used with OSSL_FUNC_asym_cipherget_ctx_params()
and OSSL_FUNC_asym_cipher_set_ctx_params() respectively.
=head1 RETURN VALUES
OSSL_FUNC_asym_cipher_newctx() and OSSL_FUNC_asym_cipher_dupctx() should return the newly
created provider side asymmetric cipher context, or NULL on failure.
All other functions should return 1 for success or 0 on error.
=head1 SEE ALSO
L<provider(7)>
=head1 HISTORY
The provider ASYM_CIPHER interface was introduced in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man7/provider-base.pod b/doc/man7/provider-base.pod
index c587e0e529b6..2fd803bb96b6 100644
--- a/doc/man7/provider-base.pod
+++ b/doc/man7/provider-base.pod
@@ -1,819 +1,819 @@
=pod
=head1 NAME
provider-base
- The basic OpenSSL library E<lt>-E<gt> provider functions
=head1 SYNOPSIS
#include <openssl/core_dispatch.h>
/*
* None of these are actual functions, but are displayed like this for
* the function signatures for functions that are offered as function
* pointers in OSSL_DISPATCH arrays.
*/
/* Functions offered by libcrypto to the providers */
const OSSL_ITEM *core_gettable_params(const OSSL_CORE_HANDLE *handle);
int core_get_params(const OSSL_CORE_HANDLE *handle, OSSL_PARAM params[]);
typedef void (*OSSL_thread_stop_handler_fn)(void *arg);
int core_thread_start(const OSSL_CORE_HANDLE *handle,
OSSL_thread_stop_handler_fn handfn,
void *arg);
OPENSSL_CORE_CTX *core_get_libctx(const OSSL_CORE_HANDLE *handle);
void core_new_error(const OSSL_CORE_HANDLE *handle);
void core_set_error_debug(const OSSL_CORE_HANDLE *handle,
const char *file, int line, const char *func);
void core_vset_error(const OSSL_CORE_HANDLE *handle,
uint32_t reason, const char *fmt, va_list args);
int core_obj_add_sigid(const OSSL_CORE_HANDLE *prov, const char *sign_name,
const char *digest_name, const char *pkey_name);
int core_obj_create(const OSSL_CORE_HANDLE *handle, const char *oid,
const char *sn, const char *ln);
/*
* Some OpenSSL functionality is directly offered to providers via
* dispatch
*/
void *CRYPTO_malloc(size_t num, const char *file, int line);
void *CRYPTO_zalloc(size_t num, const char *file, int line);
void CRYPTO_free(void *ptr, const char *file, int line);
void CRYPTO_clear_free(void *ptr, size_t num,
const char *file, int line);
void *CRYPTO_realloc(void *addr, size_t num,
const char *file, int line);
void *CRYPTO_clear_realloc(void *addr, size_t old_num, size_t num,
const char *file, int line);
void *CRYPTO_secure_malloc(size_t num, const char *file, int line);
void *CRYPTO_secure_zalloc(size_t num, const char *file, int line);
void CRYPTO_secure_free(void *ptr, const char *file, int line);
void CRYPTO_secure_clear_free(void *ptr, size_t num,
const char *file, int line);
int CRYPTO_secure_allocated(const void *ptr);
void OPENSSL_cleanse(void *ptr, size_t len);
unsigned char *OPENSSL_hexstr2buf(const char *str, long *buflen);
OSSL_CORE_BIO *BIO_new_file(const char *filename, const char *mode);
OSSL_CORE_BIO *BIO_new_membuf(const void *buf, int len);
int BIO_read_ex(OSSL_CORE_BIO *bio, void *data, size_t data_len,
size_t *bytes_read);
int BIO_write_ex(OSSL_CORE_BIO *bio, const void *data, size_t data_len,
size_t *written);
int BIO_up_ref(OSSL_CORE_BIO *bio);
int BIO_free(OSSL_CORE_BIO *bio);
int BIO_vprintf(OSSL_CORE_BIO *bio, const char *format, va_list args);
int BIO_vsnprintf(char *buf, size_t n, const char *fmt, va_list args);
void OSSL_SELF_TEST_set_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK *cb,
void *cbarg);
size_t get_entropy(const OSSL_CORE_HANDLE *handle,
unsigned char **pout, int entropy,
size_t min_len, size_t max_len);
void cleanup_entropy(const OSSL_CORE_HANDLE *handle,
unsigned char *buf, size_t len);
size_t get_nonce(const OSSL_CORE_HANDLE *handle,
unsigned char **pout, size_t min_len, size_t max_len,
const void *salt, size_t salt_len);
void cleanup_nonce(const OSSL_CORE_HANDLE *handle,
unsigned char *buf, size_t len);
/* Functions for querying the providers in the application library context */
int provider_register_child_cb(const OSSL_CORE_HANDLE *handle,
int (*create_cb)(const OSSL_CORE_HANDLE *provider,
void *cbdata),
int (*remove_cb)(const OSSL_CORE_HANDLE *provider,
void *cbdata),
int (*global_props_cb)(const char *props, void *cbdata),
void *cbdata);
void provider_deregister_child_cb(const OSSL_CORE_HANDLE *handle);
const char *provider_name(const OSSL_CORE_HANDLE *prov);
void *provider_get0_provider_ctx(const OSSL_CORE_HANDLE *prov);
const OSSL_DISPATCH *provider_get0_dispatch(const OSSL_CORE_HANDLE *prov);
int provider_up_ref(const OSSL_CORE_HANDLE *prov, int activate);
int provider_free(const OSSL_CORE_HANDLE *prov, int deactivate);
/* Functions offered by the provider to libcrypto */
void provider_teardown(void *provctx);
const OSSL_ITEM *provider_gettable_params(void *provctx);
int provider_get_params(void *provctx, OSSL_PARAM params[]);
const OSSL_ALGORITHM *provider_query_operation(void *provctx,
int operation_id,
const int *no_store);
void provider_unquery_operation(void *provctx, int operation_id,
const OSSL_ALGORITHM *algs);
const OSSL_ITEM *provider_get_reason_strings(void *provctx);
int provider_get_capabilities(void *provctx, const char *capability,
OSSL_CALLBACK *cb, void *arg);
int provider_self_test(void *provctx);
=head1 DESCRIPTION
All "functions" mentioned here are passed as function pointers between
F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays, in the call
of the provider initialization function. See L<provider(7)/Provider>
for a description of the initialization function. They are known as "upcalls".
All these "functions" have a corresponding function type definition
named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
function pointer from a L<OSSL_DISPATCH(3)> element named
B<OSSL_FUNC_{name}>.
For example, the "function" core_gettable_params() has these:
typedef OSSL_PARAM *
(OSSL_FUNC_core_gettable_params_fn)(const OSSL_CORE_HANDLE *handle);
static ossl_inline OSSL_NAME_core_gettable_params_fn
OSSL_FUNC_core_gettable_params(const OSSL_DISPATCH *opf);
L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
macros in L<openssl-core_dispatch.h(7)>, as follows:
For I<in> (the L<OSSL_DISPATCH(3)> array passed from F<libcrypto> to the
provider):
core_gettable_params OSSL_FUNC_CORE_GETTABLE_PARAMS
core_get_params OSSL_FUNC_CORE_GET_PARAMS
core_thread_start OSSL_FUNC_CORE_THREAD_START
core_get_libctx OSSL_FUNC_CORE_GET_LIBCTX
core_new_error OSSL_FUNC_CORE_NEW_ERROR
core_set_error_debug OSSL_FUNC_CORE_SET_ERROR_DEBUG
core_vset_error OSSL_FUNC_CORE_VSET_ERROR
core_obj_add_sigid OSSL_FUNC_CORE_OBJ_ADD_SIGID
core_obj_create OSSL_FUNC_CORE_OBJ_CREATE
CRYPTO_malloc OSSL_FUNC_CRYPTO_MALLOC
CRYPTO_zalloc OSSL_FUNC_CRYPTO_ZALLOC
CRYPTO_free OSSL_FUNC_CRYPTO_FREE
CRYPTO_clear_free OSSL_FUNC_CRYPTO_CLEAR_FREE
CRYPTO_realloc OSSL_FUNC_CRYPTO_REALLOC
CRYPTO_clear_realloc OSSL_FUNC_CRYPTO_CLEAR_REALLOC
CRYPTO_secure_malloc OSSL_FUNC_CRYPTO_SECURE_MALLOC
CRYPTO_secure_zalloc OSSL_FUNC_CRYPTO_SECURE_ZALLOC
CRYPTO_secure_free OSSL_FUNC_CRYPTO_SECURE_FREE
CRYPTO_secure_clear_free OSSL_FUNC_CRYPTO_SECURE_CLEAR_FREE
CRYPTO_secure_allocated OSSL_FUNC_CRYPTO_SECURE_ALLOCATED
BIO_new_file OSSL_FUNC_BIO_NEW_FILE
BIO_new_mem_buf OSSL_FUNC_BIO_NEW_MEMBUF
BIO_read_ex OSSL_FUNC_BIO_READ_EX
BIO_write_ex OSSL_FUNC_BIO_WRITE_EX
BIO_up_ref OSSL_FUNC_BIO_UP_REF
BIO_free OSSL_FUNC_BIO_FREE
BIO_vprintf OSSL_FUNC_BIO_VPRINTF
BIO_vsnprintf OSSL_FUNC_BIO_VSNPRINTF
BIO_puts OSSL_FUNC_BIO_PUTS
BIO_gets OSSL_FUNC_BIO_GETS
BIO_ctrl OSSL_FUNC_BIO_CTRL
OPENSSL_cleanse OSSL_FUNC_OPENSSL_CLEANSE
OSSL_SELF_TEST_set_callback OSSL_FUNC_SELF_TEST_CB
ossl_rand_get_entropy OSSL_FUNC_GET_ENTROPY
ossl_rand_cleanup_entropy OSSL_FUNC_CLEANUP_ENTROPY
ossl_rand_get_nonce OSSL_FUNC_GET_NONCE
ossl_rand_cleanup_nonce OSSL_FUNC_CLEANUP_NONCE
provider_register_child_cb OSSL_FUNC_PROVIDER_REGISTER_CHILD_CB
provider_deregister_child_cb OSSL_FUNC_PROVIDER_DEREGISTER_CHILD_CB
provider_name OSSL_FUNC_PROVIDER_NAME
provider_get0_provider_ctx OSSL_FUNC_PROVIDER_GET0_PROVIDER_CTX
provider_get0_dispatch OSSL_FUNC_PROVIDER_GET0_DISPATCH
provider_up_ref OSSL_FUNC_PROVIDER_UP_REF
provider_free OSSL_FUNC_PROVIDER_FREE
For I<*out> (the L<OSSL_DISPATCH(3)> array passed from the provider to
F<libcrypto>):
provider_teardown OSSL_FUNC_PROVIDER_TEARDOWN
provider_gettable_params OSSL_FUNC_PROVIDER_GETTABLE_PARAMS
provider_get_params OSSL_FUNC_PROVIDER_GET_PARAMS
provider_query_operation OSSL_FUNC_PROVIDER_QUERY_OPERATION
provider_unquery_operation OSSL_FUNC_PROVIDER_UNQUERY_OPERATION
provider_get_reason_strings OSSL_FUNC_PROVIDER_GET_REASON_STRINGS
provider_get_capabilities OSSL_FUNC_PROVIDER_GET_CAPABILITIES
provider_self_test OSSL_FUNC_PROVIDER_SELF_TEST
=head2 Core functions
core_gettable_params() returns a constant array of descriptor
L<OSSL_PARAM(3)>, for parameters that core_get_params() can handle.
core_get_params() retrieves parameters from the core for the given I<handle>.
See L</Core parameters> below for a description of currently known
parameters.
The core_thread_start() function informs the core that the provider has stated
an interest in the current thread. The core will inform the provider when the
thread eventually stops. It must be passed the I<handle> for this provider, as
well as a callback I<handfn> which will be called when the thread stops. The
callback will subsequently be called, with the supplied argument I<arg>, from
the thread that is stopping and gets passed the provider context as an
argument. This may be useful to perform thread specific clean up such as
freeing thread local variables.
core_get_libctx() retrieves the core context in which the library
object for the current provider is stored, accessible through the I<handle>.
This function is useful only for built-in providers such as the default
provider. Never cast this to OSSL_LIB_CTX in a provider that is not
built-in as the OSSL_LIB_CTX of the library loading the provider might be
a completely different structure than the OSSL_LIB_CTX of the library the
provider is linked to. Use L<OSSL_LIB_CTX_new_child(3)> instead to obtain
a proper library context that is linked to the application library context.
core_new_error(), core_set_error_debug() and core_vset_error() are
building blocks for reporting an error back to the core, with
reference to the I<handle>.
=over 4
=item core_new_error()
allocates a new thread specific error record.
This corresponds to the OpenSSL function L<ERR_new(3)>.
=item core_set_error_debug()
sets debugging information in the current thread specific error
record.
The debugging information includes the name of the file I<file>, the
line I<line> and the function name I<func> where the error occurred.
This corresponds to the OpenSSL function L<ERR_set_debug(3)>.
=item core_vset_error()
sets the I<reason> for the error, along with any addition data.
The I<reason> is a number defined by the provider and used to index
the reason strings table that's returned by
provider_get_reason_strings().
The additional data is given as a format string I<fmt> and a set of
arguments I<args>, which are treated in the same manner as with
BIO_vsnprintf().
I<file> and I<line> may also be passed to indicate exactly where the
error occurred or was reported.
This corresponds to the OpenSSL function L<ERR_vset_error(3)>.
=back
The core_obj_create() function registers a new OID and associated short name
I<sn> and long name I<ln> for the given I<handle>. It is similar to the OpenSSL
function L<OBJ_create(3)> except that it returns 1 on success or 0 on failure.
It will treat as success the case where the OID already exists (even if the
short name I<sn> or long name I<ln> provided as arguments differ from those
associated with the existing OID, in which case the new names are not
associated).
This function is not thread safe.
The core_obj_add_sigid() function registers a new composite signature algorithm
(I<sign_name>) consisting of an underlying signature algorithm (I<pkey_name>)
and digest algorithm (I<digest_name>) for the given I<handle>. It assumes that
the OIDs for the composite signature algorithm as well as for the underlying
signature and digest algorithms are either already known to OpenSSL or have been
registered via a call to core_obj_create(). It corresponds to the OpenSSL
function L<OBJ_add_sigid(3)>, except that the objects are identified by name
rather than a numeric NID. Any name (OID, short name or long name) can be used
to identify the object. It will treat as success the case where the composite
signature algorithm already exists (even if registered against a different
underlying signature or digest algorithm). For I<digest_name>, NULL or an
empty string is permissible for signature algorithms that do not need a digest
to operate correctly. The function returns 1 on success or 0 on failure.
This function is not thread safe.
CRYPTO_malloc(), CRYPTO_zalloc(), CRYPTO_free(), CRYPTO_clear_free(),
CRYPTO_realloc(), CRYPTO_clear_realloc(), CRYPTO_secure_malloc(),
CRYPTO_secure_zalloc(), CRYPTO_secure_free(),
CRYPTO_secure_clear_free(), CRYPTO_secure_allocated(),
BIO_new_file(), BIO_new_mem_buf(), BIO_read_ex(), BIO_write_ex(), BIO_up_ref(),
BIO_free(), BIO_vprintf(), BIO_vsnprintf(), BIO_gets(), BIO_puts(),
BIO_ctrl(), OPENSSL_cleanse() and
OPENSSL_hexstr2buf() correspond exactly to the public functions with
the same name. As a matter of fact, the pointers in the L<OSSL_DISPATCH(3)>
array are typically direct pointers to those public functions. Note that the BIO
functions take an B<OSSL_CORE_BIO> type rather than the standard B<BIO>
type. This is to ensure that a provider does not mix BIOs from the core
with BIOs used on the provider side (the two are not compatible).
OSSL_SELF_TEST_set_callback() is used to set an optional callback that can be
passed into a provider. This may be ignored by a provider.
get_entropy() retrieves seeding material from the operating system.
The seeding material will have at least I<entropy> bytes of randomness and the
output will have at least I<min_len> and at most I<max_len> bytes.
The buffer address is stored in I<*pout> and the buffer length is
returned to the caller. On error, zero is returned.
cleanup_entropy() is used to clean up and free the buffer returned by
get_entropy(). The entropy pointer returned by get_entropy() is passed in
B<buf> and its length in B<len>.
get_nonce() retrieves a nonce using the passed I<salt> parameter
of length I<salt_len> and operating system specific information.
The I<salt> should contain uniquely identifying information and this is
included, in an unspecified manner, as part of the output.
-The output is stored in a buffer which contrains at least I<min_len> and at
+The output is stored in a buffer which contains at least I<min_len> and at
most I<max_len> bytes. The buffer address is stored in I<*pout> and the
buffer length returned to the caller. On error, zero is returned.
cleanup_nonce() is used to clean up and free the buffer returned by
get_nonce(). The nonce pointer returned by get_nonce() is passed in
B<buf> and its length in B<len>.
provider_register_child_cb() registers callbacks for being informed about the
loading and unloading of providers in the application's library context.
I<handle> is this provider's handle and I<cbdata> is this provider's data
that will be passed back to the callbacks. It returns 1 on success or 0
otherwise. These callbacks may be called while holding locks in libcrypto. In
order to avoid deadlocks the callback implementation must not be long running
and must not call other OpenSSL API functions or upcalls.
I<create_cb> is a callback that will be called when a new provider is loaded
into the application's library context. It is also called for any providers that
are already loaded at the point that this callback is registered. The callback
is passed the handle being used for the new provider being loadded and this
provider's data in I<cbdata>. It should return 1 on success or 0 on failure.
I<remove_cb> is a callback that will be called when a new provider is unloaded
from the application's library context. It is passed the handle being used for
the provider being unloaded and this provider's data in I<cbdata>. It should
return 1 on success or 0 on failure.
I<global_props_cb> is a callback that will be called when the global properties
from the parent library context are changed. It should return 1 on success
or 0 on failure.
provider_deregister_child_cb() unregisters callbacks previously registered via
provider_register_child_cb(). If provider_register_child_cb() has been called
then provider_deregister_child_cb() should be called at or before the point that
this provider's teardown function is called.
provider_name() returns a string giving the name of the provider identified by
I<handle>.
provider_get0_provider_ctx() returns the provider context that is associated
with the provider identified by I<prov>.
provider_get0_dispatch() gets the dispatch table registered by the provider
identified by I<prov> when it initialised.
provider_up_ref() increments the reference count on the provider I<prov>. If
I<activate> is nonzero then the provider is also loaded if it is not already
loaded. It returns 1 on success or 0 on failure.
provider_free() decrements the reference count on the provider I<prov>. If
I<deactivate> is nonzero then the provider is also unloaded if it is not
already loaded. It returns 1 on success or 0 on failure.
=head2 Provider functions
provider_teardown() is called when a provider is shut down and removed
from the core's provider store.
It must free the passed I<provctx>.
provider_gettable_params() should return a constant array of
descriptor L<OSSL_PARAM(3)>, for parameters that provider_get_params()
can handle.
provider_get_params() should process the L<OSSL_PARAM(3)> array
I<params>, setting the values of the parameters it understands.
provider_query_operation() should return a constant L<OSSL_ALGORITHM(3)>
that corresponds to the given I<operation_id>.
It should indicate if the core may store a reference to this array by
setting I<*no_store> to 0 (core may store a reference) or 1 (core may
not store a reference).
provider_unquery_operation() informs the provider that the result of a
provider_query_operation() is no longer directly required and that the function
pointers have been copied. The I<operation_id> should match that passed to
provider_query_operation() and I<algs> should be its return value.
provider_get_reason_strings() should return a constant L<OSSL_ITEM(3)>
array that provides reason strings for reason codes the provider may
use when reporting errors using core_put_error().
The provider_get_capabilities() function should call the callback I<cb> passing
it a set of L<OSSL_PARAM(3)>s and the caller supplied argument I<arg>. The
L<OSSL_PARAM(3)>s should provide details about the capability with the name given
in the I<capability> argument relevant for the provider context I<provctx>. If a
provider supports multiple capabilities with the given name then it may call the
callback multiple times (one for each capability). Capabilities can be useful for
describing the services that a provider can offer. For further details see the
L</CAPABILITIES> section below. It should return 1 on success or 0 on error.
The provider_self_test() function should perform known answer tests on a subset
of the algorithms that it uses, and may also verify the integrity of the
provider module. It should return 1 on success or 0 on error. It will return 1
if this function is not used.
None of these functions are mandatory, but a provider is fairly
useless without at least provider_query_operation(), and
provider_gettable_params() is fairly useless if not accompanied by
provider_get_params().
=head2 Provider parameters
provider_get_params() can return the following provider parameters to the core:
=over 4
=item "name" (B<OSSL_PROV_PARAM_NAME>) <UTF8 ptr>
This points to a string that should give a unique name for the provider.
=item "version" (B<OSSL_PROV_PARAM_VERSION>) <UTF8 ptr>
This points to a string that is a version number associated with this provider.
OpenSSL in-built providers use OPENSSL_VERSION_STR, but this may be different
for any third party provider. This string is for informational purposes only.
=item "buildinfo" (B<OSSL_PROV_PARAM_BUILDINFO>) <UTF8 ptr>
This points to a string that is a build information associated with this provider.
OpenSSL in-built providers use OPENSSL_FULL_VERSION_STR, but this may be
different for any third party provider.
=item "status" (B<OSSL_PROV_PARAM_STATUS>) <unsigned integer>
This returns 0 if the provider has entered an error state, otherwise it returns
1.
=back
provider_gettable_params() should return the above parameters.
=head2 Core parameters
core_get_params() can retrieve the following core parameters for each provider:
=over 4
=item "openssl-version" (B<OSSL_PROV_PARAM_CORE_VERSION>) <UTF8 string ptr>
This points to the OpenSSL libraries' full version string, i.e. the string
expanded from the macro B<OPENSSL_VERSION_STR>.
=item "provider-name" (B<OSSL_PROV_PARAM_CORE_PROV_NAME>) <UTF8 string ptr>
This points to the OpenSSL libraries' idea of what the calling provider is named.
=item "module-filename" (B<OSSL_PROV_PARAM_CORE_MODULE_FILENAME>) <UTF8 string ptr>
This points to a string containing the full filename of the providers
module file.
=back
Additionally, provider specific configuration parameters from the
config file are available, in dotted name form.
The dotted name form is a concatenation of section names and final
config command name separated by periods.
For example, let's say we have the following config example:
config_diagnostics = 1
openssl_conf = openssl_init
[openssl_init]
providers = providers_sect
[providers_sect]
foo = foo_sect
[foo_sect]
activate = 1
data1 = 2
data2 = str
more = foo_more
[foo_more]
data3 = foo,bar
The provider will have these additional parameters available:
=over 4
=item "activate"
pointing at the string "1"
=item "data1"
pointing at the string "2"
=item "data2"
pointing at the string "str"
=item "more.data3"
pointing at the string "foo,bar"
=back
For more information on handling parameters, see L<OSSL_PARAM(3)> as
L<OSSL_PARAM_int(3)>.
=head1 CAPABILITIES
Capabilities describe some of the services that a provider can offer.
Applications can query the capabilities to discover those services.
=head3 "TLS-GROUP" Capability
The "TLS-GROUP" capability can be queried by libssl to discover the list of
TLS groups that a provider can support. Each group supported can be used for
I<key exchange> (KEX) or I<key encapsulation method> (KEM) during a TLS
handshake.
TLS clients can advertise the list of TLS groups they support in the
supported_groups extension, and TLS servers can select a group from the offered
list that they also support. In this way a provider can add to the list of
groups that libssl already supports with additional ones.
Each TLS group that a provider supports should be described via the callback
passed in through the provider_get_capabilities function. Each group should have
the following details supplied (all are mandatory, except
B<OSSL_CAPABILITY_TLS_GROUP_IS_KEM>):
=over 4
=item "tls-group-name" (B<OSSL_CAPABILITY_TLS_GROUP_NAME>) <UTF8 string>
The name of the group as given in the IANA TLS Supported Groups registry
L<https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8>.
=item "tls-group-name-internal" (B<OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL>) <UTF8 string>
The name of the group as known by the provider. This could be the same as the
"tls-group-name", but does not have to be.
=item "tls-group-id" (B<OSSL_CAPABILITY_TLS_GROUP_ID>) <unsigned integer>
The TLS group id value as given in the IANA TLS Supported Groups registry.
=item "tls-group-alg" (B<OSSL_CAPABILITY_TLS_GROUP_ALG>) <UTF8 string>
The name of a Key Management algorithm that the provider offers and that should
be used with this group. Keys created should be able to support I<key exchange>
or I<key encapsulation method> (KEM), as implied by the optional
B<OSSL_CAPABILITY_TLS_GROUP_IS_KEM> flag.
The algorithm must support key and parameter generation as well as the
key/parameter generation parameter, B<OSSL_PKEY_PARAM_GROUP_NAME>. The group
name given via "tls-group-name-internal" above will be passed via
B<OSSL_PKEY_PARAM_GROUP_NAME> when libssl wishes to generate keys/parameters.
=item "tls-group-sec-bits" (B<OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS>) <unsigned integer>
The number of bits of security offered by keys in this group. The number of bits
should be comparable with the ones given in table 2 and 3 of the NIST SP800-57
document.
=item "tls-group-is-kem" (B<OSSL_CAPABILITY_TLS_GROUP_IS_KEM>) <unsigned integer>
Boolean flag to describe if the group should be used in I<key exchange> (KEX)
mode (0, default) or in I<key encapsulation method> (KEM) mode (1).
This parameter is optional: if not specified, KEX mode is assumed as the default
mode for the group.
In KEX mode, in a typical Diffie-Hellman fashion, both sides execute I<keygen>
then I<derive> against the peer public key. To operate in KEX mode, the group
implementation must support the provider functions as described in
L<provider-keyexch(7)>.
In KEM mode, the client executes I<keygen> and sends its public key, the server
executes I<encapsulate> using the client's public key and sends back the
resulting I<ciphertext>, finally the client executes I<decapsulate> to retrieve
the same I<shared secret> generated by the server's I<encapsulate>. To operate
in KEM mode, the group implementation must support the provider functions as
described in L<provider-kem(7)>.
Both in KEX and KEM mode, the resulting I<shared secret> is then used according
to the protocol specification.
=item "tls-min-tls" (B<OSSL_CAPABILITY_TLS_GROUP_MIN_TLS>) <integer>
=item "tls-max-tls" (B<OSSL_CAPABILITY_TLS_GROUP_MAX_TLS>) <integer>
=item "tls-min-dtls" (B<OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS>) <integer>
=item "tls-max-dtls" (B<OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS>) <integer>
These parameters can be used to describe the minimum and maximum TLS and DTLS
versions supported by the group. The values equate to the on-the-wire encoding
of the various TLS versions. For example TLSv1.3 is 0x0304 (772 decimal), and
TLSv1.2 is 0x0303 (771 decimal). A 0 indicates that there is no defined minimum
or maximum. A -1 indicates that the group should not be used in that protocol.
=back
=head1 EXAMPLES
This is an example of a simple provider made available as a
dynamically loadable module.
It implements the fictitious algorithm C<FOO> for the fictitious
operation C<BAR>.
#include <malloc.h>
#include <openssl/core.h>
#include <openssl/core_dispatch.h>
/* Errors used in this provider */
#define E_MALLOC 1
static const OSSL_ITEM reasons[] = {
{ E_MALLOC, "memory allocation failure" }.
{ 0, NULL } /* Termination */
};
/*
* To ensure we get the function signature right, forward declare
* them using function types provided by openssl/core_dispatch.h
*/
OSSL_FUNC_bar_newctx_fn foo_newctx;
OSSL_FUNC_bar_freectx_fn foo_freectx;
OSSL_FUNC_bar_init_fn foo_init;
OSSL_FUNC_bar_update_fn foo_update;
OSSL_FUNC_bar_final_fn foo_final;
OSSL_FUNC_provider_query_operation_fn p_query;
OSSL_FUNC_provider_get_reason_strings_fn p_reasons;
OSSL_FUNC_provider_teardown_fn p_teardown;
OSSL_provider_init_fn OSSL_provider_init;
OSSL_FUNC_core_put_error *c_put_error = NULL;
/* Provider context */
struct prov_ctx_st {
OSSL_CORE_HANDLE *handle;
}
/* operation context for the algorithm FOO */
struct foo_ctx_st {
struct prov_ctx_st *provctx;
int b;
};
static void *foo_newctx(void *provctx)
{
struct foo_ctx_st *fooctx = malloc(sizeof(*fooctx));
if (fooctx != NULL)
fooctx->provctx = provctx;
else
c_put_error(provctx->handle, E_MALLOC, __FILE__, __LINE__);
return fooctx;
}
static void foo_freectx(void *fooctx)
{
free(fooctx);
}
static int foo_init(void *vfooctx)
{
struct foo_ctx_st *fooctx = vfooctx;
fooctx->b = 0x33;
}
static int foo_update(void *vfooctx, unsigned char *in, size_t inl)
{
struct foo_ctx_st *fooctx = vfooctx;
/* did you expect something serious? */
if (inl == 0)
return 1;
for (; inl-- > 0; in++)
*in ^= fooctx->b;
return 1;
}
static int foo_final(void *vfooctx)
{
struct foo_ctx_st *fooctx = vfooctx;
fooctx->b = 0x66;
}
static const OSSL_DISPATCH foo_fns[] = {
{ OSSL_FUNC_BAR_NEWCTX, (void (*)(void))foo_newctx },
{ OSSL_FUNC_BAR_FREECTX, (void (*)(void))foo_freectx },
{ OSSL_FUNC_BAR_INIT, (void (*)(void))foo_init },
{ OSSL_FUNC_BAR_UPDATE, (void (*)(void))foo_update },
{ OSSL_FUNC_BAR_FINAL, (void (*)(void))foo_final },
{ 0, NULL }
};
static const OSSL_ALGORITHM bars[] = {
{ "FOO", "provider=chumbawamba", foo_fns },
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM *p_query(void *provctx, int operation_id,
int *no_store)
{
switch (operation_id) {
case OSSL_OP_BAR:
return bars;
}
return NULL;
}
static const OSSL_ITEM *p_reasons(void *provctx)
{
return reasons;
}
static void p_teardown(void *provctx)
{
free(provctx);
}
static const OSSL_DISPATCH prov_fns[] = {
{ OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))p_teardown },
{ OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))p_query },
{ OSSL_FUNC_PROVIDER_GET_REASON_STRINGS, (void (*)(void))p_reasons },
{ 0, NULL }
};
int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
const OSSL_DISPATCH *in,
const OSSL_DISPATCH **out,
void **provctx)
{
struct prov_ctx_st *pctx = NULL;
for (; in->function_id != 0; in++)
switch (in->function_id) {
case OSSL_FUNC_CORE_PUT_ERROR:
c_put_error = OSSL_FUNC_core_put_error(in);
break;
}
*out = prov_fns;
if ((pctx = malloc(sizeof(*pctx))) == NULL) {
/*
* ALEA IACTA EST, if the core retrieves the reason table
* regardless, that string will be displayed, otherwise not.
*/
c_put_error(handle, E_MALLOC, __FILE__, __LINE__);
return 0;
}
pctx->handle = handle;
return 1;
}
This relies on a few things existing in F<openssl/core_dispatch.h>:
#define OSSL_OP_BAR 4711
#define OSSL_FUNC_BAR_NEWCTX 1
typedef void *(OSSL_FUNC_bar_newctx_fn)(void *provctx);
static ossl_inline OSSL_FUNC_bar_newctx(const OSSL_DISPATCH *opf)
{ return (OSSL_FUNC_bar_newctx_fn *)opf->function; }
#define OSSL_FUNC_BAR_FREECTX 2
typedef void (OSSL_FUNC_bar_freectx_fn)(void *ctx);
- static ossl_inline OSSL_FUNC_bar_newctx(const OSSL_DISPATCH *opf)
+ static ossl_inline OSSL_FUNC_bar_freectx(const OSSL_DISPATCH *opf)
{ return (OSSL_FUNC_bar_freectx_fn *)opf->function; }
#define OSSL_FUNC_BAR_INIT 3
typedef void *(OSSL_FUNC_bar_init_fn)(void *ctx);
static ossl_inline OSSL_FUNC_bar_init(const OSSL_DISPATCH *opf)
{ return (OSSL_FUNC_bar_init_fn *)opf->function; }
#define OSSL_FUNC_BAR_UPDATE 4
typedef void *(OSSL_FUNC_bar_update_fn)(void *ctx,
unsigned char *in, size_t inl);
static ossl_inline OSSL_FUNC_bar_update(const OSSL_DISPATCH *opf)
{ return (OSSL_FUNC_bar_update_fn *)opf->function; }
#define OSSL_FUNC_BAR_FINAL 5
typedef void *(OSSL_FUNC_bar_final_fn)(void *ctx);
static ossl_inline OSSL_FUNC_bar_final(const OSSL_DISPATCH *opf)
{ return (OSSL_FUNC_bar_final_fn *)opf->function; }
=head1 SEE ALSO
L<provider(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.
+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/doc/man7/provider-cipher.pod b/doc/man7/provider-cipher.pod
index 1faf698107be..14ff581c72c4 100644
--- a/doc/man7/provider-cipher.pod
+++ b/doc/man7/provider-cipher.pod
@@ -1,247 +1,247 @@
=pod
=head1 NAME
provider-cipher - The cipher library E<lt>-E<gt> provider functions
=head1 SYNOPSIS
=for openssl multiple includes
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
/*
* None of these are actual functions, but are displayed like this for
* the function signatures for functions that are offered as function
* pointers in OSSL_DISPATCH arrays.
*/
/* Context management */
void *OSSL_FUNC_cipher_newctx(void *provctx);
void OSSL_FUNC_cipher_freectx(void *cctx);
void *OSSL_FUNC_cipher_dupctx(void *cctx);
/* Encryption/decryption */
int OSSL_FUNC_cipher_encrypt_init(void *cctx, const unsigned char *key,
size_t keylen, const unsigned char *iv,
size_t ivlen, const OSSL_PARAM params[]);
int OSSL_FUNC_cipher_decrypt_init(void *cctx, const unsigned char *key,
size_t keylen, const unsigned char *iv,
size_t ivlen, const OSSL_PARAM params[]);
int OSSL_FUNC_cipher_update(void *cctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in, size_t inl);
int OSSL_FUNC_cipher_final(void *cctx, unsigned char *out, size_t *outl,
size_t outsize);
int OSSL_FUNC_cipher_cipher(void *cctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in, size_t inl);
/* Cipher parameter descriptors */
const OSSL_PARAM *OSSL_FUNC_cipher_gettable_params(void *provctx);
/* Cipher operation parameter descriptors */
const OSSL_PARAM *OSSL_FUNC_cipher_gettable_ctx_params(void *cctx,
void *provctx);
const OSSL_PARAM *OSSL_FUNC_cipher_settable_ctx_params(void *cctx,
void *provctx);
/* Cipher parameters */
int OSSL_FUNC_cipher_get_params(OSSL_PARAM params[]);
/* Cipher operation parameters */
int OSSL_FUNC_cipher_get_ctx_params(void *cctx, OSSL_PARAM params[]);
int OSSL_FUNC_cipher_set_ctx_params(void *cctx, const OSSL_PARAM params[]);
=head1 DESCRIPTION
This documentation is primarily aimed at provider authors. See L<provider(7)>
for further information.
The CIPHER operation enables providers to implement cipher algorithms and make
them available to applications via the API functions L<EVP_EncryptInit_ex(3)>,
L<EVP_EncryptUpdate(3)> and L<EVP_EncryptFinal(3)> (as well as the decrypt
equivalents and other related functions).
All "functions" mentioned here are passed as function pointers between
F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
provider_query_operation() function
(see L<provider-base(7)/Provider Functions>).
All these "functions" have a corresponding function type definition
named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
function pointer from an L<OSSL_DISPATCH(3)> element named
B<OSSL_FUNC_{name}>.
For example, the "function" OSSL_FUNC_cipher_newctx() has these:
typedef void *(OSSL_FUNC_cipher_newctx_fn)(void *provctx);
static ossl_inline OSSL_FUNC_cipher_newctx_fn
OSSL_FUNC_cipher_newctx(const OSSL_DISPATCH *opf);
L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
macros in L<openssl-core_dispatch.h(7)>, as follows:
OSSL_FUNC_cipher_newctx OSSL_FUNC_CIPHER_NEWCTX
OSSL_FUNC_cipher_freectx OSSL_FUNC_CIPHER_FREECTX
OSSL_FUNC_cipher_dupctx OSSL_FUNC_CIPHER_DUPCTX
OSSL_FUNC_cipher_encrypt_init OSSL_FUNC_CIPHER_ENCRYPT_INIT
OSSL_FUNC_cipher_decrypt_init OSSL_FUNC_CIPHER_DECRYPT_INIT
OSSL_FUNC_cipher_update OSSL_FUNC_CIPHER_UPDATE
OSSL_FUNC_cipher_final OSSL_FUNC_CIPHER_FINAL
OSSL_FUNC_cipher_cipher OSSL_FUNC_CIPHER_CIPHER
OSSL_FUNC_cipher_get_params OSSL_FUNC_CIPHER_GET_PARAMS
OSSL_FUNC_cipher_get_ctx_params OSSL_FUNC_CIPHER_GET_CTX_PARAMS
OSSL_FUNC_cipher_set_ctx_params OSSL_FUNC_CIPHER_SET_CTX_PARAMS
OSSL_FUNC_cipher_gettable_params OSSL_FUNC_CIPHER_GETTABLE_PARAMS
OSSL_FUNC_cipher_gettable_ctx_params OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS
OSSL_FUNC_cipher_settable_ctx_params OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS
A cipher algorithm implementation may not implement all of these functions.
In order to be a consistent set of functions there must at least be a complete
set of "encrypt" functions, or a complete set of "decrypt" functions, or a
single "cipher" function.
In all cases both the OSSL_FUNC_cipher_newctx and OSSL_FUNC_cipher_freectx functions must be
present.
All other functions are optional.
=head2 Context Management Functions
OSSL_FUNC_cipher_newctx() should create and return a pointer to a provider side
structure for holding context information during a cipher operation.
A pointer to this context will be passed back in a number of the other cipher
operation function calls.
The parameter I<provctx> is the provider context generated during provider
initialisation (see L<provider(7)>).
OSSL_FUNC_cipher_freectx() is passed a pointer to the provider side cipher context in
the I<cctx> parameter.
This function should free any resources associated with that context.
OSSL_FUNC_cipher_dupctx() should duplicate the provider side cipher context in the
I<cctx> parameter and return the duplicate copy.
=head2 Encryption/Decryption Functions
OSSL_FUNC_cipher_encrypt_init() initialises a cipher operation for encryption given a
newly created provider side cipher context in the I<cctx> parameter.
The key to be used is given in I<key> which is I<keylen> bytes long.
The IV to be used is given in I<iv> which is I<ivlen> bytes long.
The I<params>, if not NULL, should be set on the context in a manner similar to
using OSSL_FUNC_cipher_set_ctx_params().
OSSL_FUNC_cipher_decrypt_init() is the same as OSSL_FUNC_cipher_encrypt_init() except that it
initialises the context for a decryption operation.
OSSL_FUNC_cipher_update() is called to supply data to be encrypted/decrypted as part of
a previously initialised cipher operation.
The I<cctx> parameter contains a pointer to a previously initialised provider
side context.
OSSL_FUNC_cipher_update() should encrypt/decrypt I<inl> bytes of data at the location
pointed to by I<in>.
The encrypted data should be stored in I<out> and the amount of data written to
I<*outl> which should not exceed I<outsize> bytes.
OSSL_FUNC_cipher_update() may be called multiple times for a single cipher operation.
It is the responsibility of the cipher implementation to handle input lengths
that are not multiples of the block length.
In such cases a cipher implementation will typically cache partial blocks of
input data until a complete block is obtained.
I<out> may be the same location as I<in> but it should not partially overlap.
The same expectations apply to I<outsize> as documented for
L<EVP_EncryptUpdate(3)> and L<EVP_DecryptUpdate(3)>.
OSSL_FUNC_cipher_final() completes an encryption or decryption started through previous
OSSL_FUNC_cipher_encrypt_init() or OSSL_FUNC_cipher_decrypt_init(), and OSSL_FUNC_cipher_update()
calls.
The I<cctx> parameter contains a pointer to the provider side context.
Any final encryption/decryption output should be written to I<out> and the
amount of data written to I<*outl> which should not exceed I<outsize> bytes.
The same expectations apply to I<outsize> as documented for
L<EVP_EncryptFinal(3)> and L<EVP_DecryptFinal(3)>.
OSSL_FUNC_cipher_cipher() performs encryption/decryption using the provider side cipher
context in the I<cctx> parameter that should have been previously initialised via
a call to OSSL_FUNC_cipher_encrypt_init() or OSSL_FUNC_cipher_decrypt_init().
This should call the raw underlying cipher function without any padding.
This will be invoked in the provider as a result of the application calling
L<EVP_Cipher(3)>.
The application is responsible for ensuring that the input is a multiple of the
block length.
The data to be encrypted/decrypted will be in I<in>, and it will be I<inl> bytes
in length.
The output from the encryption/decryption should be stored in I<out> and the
amount of data stored should be put in I<*outl> which should be no more than
I<outsize> bytes.
=head2 Cipher Parameters
See L<OSSL_PARAM(3)> for further details on the parameters structure used by
these functions.
OSSL_FUNC_cipher_get_params() gets details of the algorithm implementation
and stores them in I<params>.
OSSL_FUNC_cipher_set_ctx_params() sets cipher operation parameters for the
provider side cipher context I<cctx> to I<params>.
Any parameter settings are additional to any that were previously set.
Passing NULL for I<params> should return true.
OSSL_FUNC_cipher_get_ctx_params() gets cipher operation details details from
the given provider side cipher context I<cctx> and stores them in I<params>.
Passing NULL for I<params> should return true.
OSSL_FUNC_cipher_gettable_params(), OSSL_FUNC_cipher_gettable_ctx_params(),
and OSSL_FUNC_cipher_settable_ctx_params() all return constant L<OSSL_PARAM(3)>
arrays as descriptors of the parameters that OSSL_FUNC_cipher_get_params(),
OSSL_FUNC_cipher_get_ctx_params(), and OSSL_FUNC_cipher_set_ctx_params()
can handle, respectively. OSSL_FUNC_cipher_gettable_ctx_params() and
OSSL_FUNC_cipher_settable_ctx_params() will return the parameters associated
with the provider side context I<cctx> in its current state if it is
not NULL. Otherwise, they return the parameters associated with the
provider side algorithm I<provctx>.
Parameters currently recognised by built-in ciphers are listed in
L<EVP_EncryptInit(3)/PARAMETERS>.
Not all parameters are relevant to, or are understood by all ciphers.
=head1 RETURN VALUES
OSSL_FUNC_cipher_newctx() and OSSL_FUNC_cipher_dupctx() should return the newly created
provider side cipher context, or NULL on failure.
OSSL_FUNC_cipher_encrypt_init(), OSSL_FUNC_cipher_decrypt_init(), OSSL_FUNC_cipher_update(),
OSSL_FUNC_cipher_final(), OSSL_FUNC_cipher_cipher(), OSSL_FUNC_cipher_get_params(),
OSSL_FUNC_cipher_get_ctx_params() and OSSL_FUNC_cipher_set_ctx_params() should return 1 for
success or 0 on error.
OSSL_FUNC_cipher_gettable_params(), OSSL_FUNC_cipher_gettable_ctx_params() and
OSSL_FUNC_cipher_settable_ctx_params() should return a constant L<OSSL_PARAM(3)>
array, or NULL if none is offered.
=head1 SEE ALSO
L<provider(7)>, L<OSSL_PROVIDER-FIPS(7)>, L<OSSL_PROVIDER-default(7)>,
L<OSSL_PROVIDER-legacy(7)>,
L<EVP_CIPHER-AES(7)>, L<EVP_CIPHER-ARIA(7)>, L<EVP_CIPHER-BLOWFISH(7)>,
L<EVP_CIPHER-CAMELLIA(7)>, L<EVP_CIPHER-CAST(7)>, L<EVP_CIPHER-CHACHA(7)>,
L<EVP_CIPHER-DES(7)>, L<EVP_CIPHER-IDEA(7)>, L<EVP_CIPHER-RC2(7)>,
L<EVP_CIPHER-RC4(7)>, L<EVP_CIPHER-RC5(7)>, L<EVP_CIPHER-SEED(7)>,
-L<EVP_CIPHER-SM4(7)>,
+L<EVP_CIPHER-SM4(7)>, L<EVP_CIPHER-NULL(7)>,
L<life_cycle-cipher(7)>, L<EVP_EncryptInit(3)>
=head1 HISTORY
The provider CIPHER interface was introduced in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man7/provider-decoder.pod b/doc/man7/provider-decoder.pod
index f279955a6088..e968e661f7cf 100644
--- a/doc/man7/provider-decoder.pod
+++ b/doc/man7/provider-decoder.pod
@@ -1,312 +1,312 @@
=pod
=head1 NAME
provider-decoder - The OSSL_DECODER library E<lt>-E<gt> provider functions
=head1 SYNOPSIS
#include <openssl/core_dispatch.h>
/*
* None of these are actual functions, but are displayed like this for
* the function signatures for functions that are offered as function
* pointers in OSSL_DISPATCH arrays.
*/
/* Decoder parameter accessor and descriptor */
const OSSL_PARAM *OSSL_FUNC_decoder_gettable_params(void *provctx);
int OSSL_FUNC_decoder_get_params(OSSL_PARAM params[]);
/* Functions to construct / destruct / manipulate the decoder context */
void *OSSL_FUNC_decoder_newctx(void *provctx);
void OSSL_FUNC_decoder_freectx(void *ctx);
const OSSL_PARAM *OSSL_FUNC_decoder_settable_ctx_params(void *provctx);
int OSSL_FUNC_decoder_set_ctx_params(void *ctx, const OSSL_PARAM params[]);
/* Functions to check selection support */
int OSSL_FUNC_decoder_does_selection(void *provctx, int selection);
/* Functions to decode object data */
int OSSL_FUNC_decoder_decode(void *ctx, OSSL_CORE_BIO *in,
int selection,
OSSL_CALLBACK *data_cb, void *data_cbarg,
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg);
/* Functions to export a decoded object */
- void *OSSL_FUNC_decoder_export_object(void *ctx,
+ int OSSL_FUNC_decoder_export_object(void *ctx,
const void *objref, size_t objref_sz,
OSSL_CALLBACK *export_cb,
void *export_cbarg);
=head1 DESCRIPTION
I<The term "decode" is used throughout this manual. This includes but is
not limited to deserialization as individual decoders can also do
decoding into intermediate data formats.>
The DECODER operation is a generic method to create a provider-native
object reference or intermediate decoded data from an encoded form
read from the given B<OSSL_CORE_BIO>. If the caller wants to decode
data from memory, it should provide a L<BIO_s_mem(3)> B<BIO>. The decoded
data or object reference is passed along with eventual metadata
to the I<metadata_cb> as L<OSSL_PARAM(3)> parameters.
The decoder doesn't need to know more about the B<OSSL_CORE_BIO>
pointer than being able to pass it to the appropriate BIO upcalls (see
L<provider-base(7)/Core functions>).
The DECODER implementation may be part of a chain, where data is
passed from one to the next. For example, there may be an
implementation to decode an object from PEM to DER, and another one
that decodes DER to a provider-native object.
The last decoding step in the decoding chain is usually supposed to create
a provider-native object referenced by an object reference. To import
that object into a different provider the OSSL_FUNC_decoder_export_object()
can be called as the final step of the decoding process.
All "functions" mentioned here are passed as function pointers between
F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
provider_query_operation() function
(see L<provider-base(7)/Provider Functions>).
All these "functions" have a corresponding function type definition
named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
function pointer from an L<OSSL_DISPATCH(3)> element named
B<OSSL_FUNC_{name}>.
For example, the "function" OSSL_FUNC_decoder_decode() has these:
typedef int
(OSSL_FUNC_decoder_decode_fn)(void *ctx, OSSL_CORE_BIO *in,
int selection,
OSSL_CALLBACK *data_cb, void *data_cbarg,
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg);
- static ossl_inline OSSL_FUNC_decoder_decode_fn
+ static ossl_inline OSSL_FUNC_decoder_decode_fn*
OSSL_FUNC_decoder_decode(const OSSL_DISPATCH *opf);
L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
macros in L<openssl-core_dispatch.h(7)>, as follows:
OSSL_FUNC_decoder_get_params OSSL_FUNC_DECODER_GET_PARAMS
OSSL_FUNC_decoder_gettable_params OSSL_FUNC_DECODER_GETTABLE_PARAMS
OSSL_FUNC_decoder_newctx OSSL_FUNC_DECODER_NEWCTX
OSSL_FUNC_decoder_freectx OSSL_FUNC_DECODER_FREECTX
OSSL_FUNC_decoder_set_ctx_params OSSL_FUNC_DECODER_SET_CTX_PARAMS
OSSL_FUNC_decoder_settable_ctx_params OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS
OSSL_FUNC_decoder_does_selection OSSL_FUNC_DECODER_DOES_SELECTION
OSSL_FUNC_decoder_decode OSSL_FUNC_DECODER_DECODE
OSSL_FUNC_decoder_export_object OSSL_FUNC_DECODER_EXPORT_OBJECT
=head2 Names and properties
The name of an implementation should match the target type of object
it decodes. For example, an implementation that decodes an RSA key
should be named "RSA". Likewise, an implementation that decodes DER data
from PEM input should be named "DER".
Properties can be used to further specify details about an implementation:
=over 4
=item input
This property is used to specify what format of input the implementation
can decode.
This property is I<mandatory>.
OpenSSL providers recognize the following input types:
=over 4
=item pem
An implementation with that input type decodes PEM formatted data.
=item der
An implementation with that input type decodes DER formatted data.
=item msblob
An implementation with that input type decodes MSBLOB formatted data.
=item pvk
An implementation with that input type decodes PVK formatted data.
=back
=item structure
This property is used to specify the structure that the decoded data is
expected to have.
This property is I<optional>.
Structures currently recognised by built-in decoders:
=over 4
=item "type-specific"
Type specific structure.
=item "pkcs8"
Structure according to the PKCS#8 specification.
=item "SubjectPublicKeyInfo"
Encoding of public keys according to the Subject Public Key Info of RFC 5280.
=back
=back
The possible values of both these properties is open ended. A provider may
very well specify input types and structures that libcrypto doesn't know
anything about.
=head2 Subset selections
Sometimes, an object has more than one subset of data that is interesting to
treat separately or together. It's possible to specify what subsets are to
be decoded, with a set of bits I<selection> that are passed in an B<int>.
This set of bits depend entirely on what kind of provider-side object is
to be decoded. For example, those bits are assumed to be the same as those
used with L<provider-keymgmt(7)> (see L<provider-keymgmt(7)/Key Objects>) when
the object is an asymmetric keypair - e.g., B<OSSL_KEYMGMT_SELECT_PRIVATE_KEY>
if the object to be decoded is supposed to contain private key components.
OSSL_FUNC_decoder_does_selection() should tell if a particular implementation
supports any of the combinations given by I<selection>.
=head2 Context functions
OSSL_FUNC_decoder_newctx() returns a context to be used with the rest of
the functions.
OSSL_FUNC_decoder_freectx() frees the given I<ctx> as created by
OSSL_FUNC_decoder_newctx().
OSSL_FUNC_decoder_set_ctx_params() sets context data according to parameters
from I<params> that it recognises. Unrecognised parameters should be
ignored.
Passing NULL for I<params> should return true.
OSSL_FUNC_decoder_settable_ctx_params() returns a constant L<OSSL_PARAM(3)>
array describing the parameters that OSSL_FUNC_decoder_set_ctx_params()
can handle.
See L<OSSL_PARAM(3)> for further details on the parameters structure used by
OSSL_FUNC_decoder_set_ctx_params() and OSSL_FUNC_decoder_settable_ctx_params().
=head2 Export function
When a provider-native object is created by a decoder it would be unsuitable
for direct use with a foreign provider. The export function allows for
exporting the object into that foreign provider if the foreign provider
supports the type of the object and provides an import function.
OSSL_FUNC_decoder_export_object() should export the object of size I<objref_sz>
referenced by I<objref> as an L<OSSL_PARAM(3)> array and pass that into the
I<export_cb> as well as the given I<export_cbarg>.
=head2 Decoding functions
OSSL_FUNC_decoder_decode() should decode the data as read from
the B<OSSL_CORE_BIO> I<in> to produce decoded data or an object to be
passed as reference in an L<OSSL_PARAM(3)> array along with possible other
metadata that was decoded from the input. This L<OSSL_PARAM(3)> array is
then passed to the I<data_cb> callback. The I<selection> bits,
if relevant, should determine what the input data should contain.
The decoding functions also take an L<OSSL_PASSPHRASE_CALLBACK(3)> function
pointer along with a pointer to application data I<cbarg>, which should be
used when a pass phrase prompt is needed.
It's important to understand that the return value from this function is
interpreted as follows:
=over 4
=item True (1)
This means "carry on the decoding process", and is meaningful even though
this function couldn't decode the input into anything, because there may be
another decoder implementation that can decode it into something.
The I<data_cb> callback should never be called when this function can't
decode the input into anything.
=item False (0)
This means "stop the decoding process", and is meaningful when the input
could be decoded into some sort of object that this function understands,
but further treatment of that object results into errors that won't be
possible for some other decoder implementation to get a different result.
=back
The conditions to stop the decoding process are at the discretion of the
implementation.
=head2 Decoder operation parameters
There are currently no operation parameters currently recognised by the
built-in decoders.
Parameters currently recognised by the built-in pass phrase callback:
=over 4
=item "info" (B<OSSL_PASSPHRASE_PARAM_INFO>) <UTF8 string>
A string of information that will become part of the pass phrase
prompt. This could be used to give the user information on what kind
of object it's being prompted for.
=back
=head1 RETURN VALUES
OSSL_FUNC_decoder_newctx() returns a pointer to a context, or NULL on
failure.
OSSL_FUNC_decoder_set_ctx_params() returns 1, unless a recognised
parameter was invalid or caused an error, for which 0 is returned.
OSSL_FUNC_decoder_settable_ctx_params() returns a pointer to an array of
constant L<OSSL_PARAM(3)> elements.
OSSL_FUNC_decoder_does_selection() returns 1 if the decoder implementation
supports any of the I<selection> bits, otherwise 0.
OSSL_FUNC_decoder_decode() returns 1 to signal that the decoding process
should continue, or 0 to signal that it should stop.
=head1 SEE ALSO
L<provider(7)>
=head1 HISTORY
The DECODER interface was introduced in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man7/provider-digest.pod b/doc/man7/provider-digest.pod
index c96dfe396676..cac53ac291fe 100644
--- a/doc/man7/provider-digest.pod
+++ b/doc/man7/provider-digest.pod
@@ -1,286 +1,287 @@
=pod
=head1 NAME
provider-digest - The digest library E<lt>-E<gt> provider functions
=head1 SYNOPSIS
=for openssl multiple includes
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
/*
* Digests support the following function signatures in OSSL_DISPATCH arrays.
* (The function signatures are not actual functions).
*/
/* Context management */
void *OSSL_FUNC_digest_newctx(void *provctx);
void OSSL_FUNC_digest_freectx(void *dctx);
void *OSSL_FUNC_digest_dupctx(void *dctx);
/* Digest generation */
int OSSL_FUNC_digest_init(void *dctx, const OSSL_PARAM params[]);
int OSSL_FUNC_digest_update(void *dctx, const unsigned char *in, size_t inl);
int OSSL_FUNC_digest_final(void *dctx, unsigned char *out, size_t *outl,
size_t outsz);
int OSSL_FUNC_digest_digest(void *provctx, const unsigned char *in, size_t inl,
unsigned char *out, size_t *outl, size_t outsz);
/* Digest parameter descriptors */
const OSSL_PARAM *OSSL_FUNC_digest_gettable_params(void *provctx);
/* Digest operation parameter descriptors */
const OSSL_PARAM *OSSL_FUNC_digest_gettable_ctx_params(void *dctx,
void *provctx);
const OSSL_PARAM *OSSL_FUNC_digest_settable_ctx_params(void *dctx,
void *provctx);
/* Digest parameters */
int OSSL_FUNC_digest_get_params(OSSL_PARAM params[]);
/* Digest operation parameters */
int OSSL_FUNC_digest_set_ctx_params(void *dctx, const OSSL_PARAM params[]);
int OSSL_FUNC_digest_get_ctx_params(void *dctx, OSSL_PARAM params[]);
=head1 DESCRIPTION
This documentation is primarily aimed at provider authors. See L<provider(7)>
for further information.
The DIGEST operation enables providers to implement digest algorithms and make
them available to applications via the API functions L<EVP_DigestInit_ex(3)>,
L<EVP_DigestUpdate(3)> and L<EVP_DigestFinal(3)> (and other related functions).
All "functions" mentioned here are passed as function pointers between
F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
provider_query_operation() function
(see L<provider-base(7)/Provider Functions>).
All these "functions" have a corresponding function type definition
named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
function pointer from an L<OSSL_DISPATCH(3)> element named
B<OSSL_FUNC_{name}>.
For example, the "function" OSSL_FUNC_digest_newctx() has these:
typedef void *(OSSL_FUNC_digest_newctx_fn)(void *provctx);
static ossl_inline OSSL_FUNC_digest_newctx_fn
OSSL_FUNC_digest_newctx(const OSSL_DISPATCH *opf);
L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
macros in L<openssl-core_dispatch.h(7)>, as follows:
OSSL_FUNC_digest_newctx OSSL_FUNC_DIGEST_NEWCTX
OSSL_FUNC_digest_freectx OSSL_FUNC_DIGEST_FREECTX
OSSL_FUNC_digest_dupctx OSSL_FUNC_DIGEST_DUPCTX
OSSL_FUNC_digest_init OSSL_FUNC_DIGEST_INIT
OSSL_FUNC_digest_update OSSL_FUNC_DIGEST_UPDATE
OSSL_FUNC_digest_final OSSL_FUNC_DIGEST_FINAL
OSSL_FUNC_digest_digest OSSL_FUNC_DIGEST_DIGEST
OSSL_FUNC_digest_get_params OSSL_FUNC_DIGEST_GET_PARAMS
OSSL_FUNC_digest_get_ctx_params OSSL_FUNC_DIGEST_GET_CTX_PARAMS
OSSL_FUNC_digest_set_ctx_params OSSL_FUNC_DIGEST_SET_CTX_PARAMS
OSSL_FUNC_digest_gettable_params OSSL_FUNC_DIGEST_GETTABLE_PARAMS
OSSL_FUNC_digest_gettable_ctx_params OSSL_FUNC_DIGEST_GETTABLE_CTX_PARAMS
OSSL_FUNC_digest_settable_ctx_params OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS
A digest algorithm implementation may not implement all of these functions.
In order to be usable all or none of OSSL_FUNC_digest_newctx, OSSL_FUNC_digest_freectx,
OSSL_FUNC_digest_init, OSSL_FUNC_digest_update and OSSL_FUNC_digest_final should be implemented.
All other functions are optional.
=head2 Context Management Functions
OSSL_FUNC_digest_newctx() should create and return a pointer to a provider side
structure for holding context information during a digest operation.
A pointer to this context will be passed back in a number of the other digest
operation function calls.
The parameter I<provctx> is the provider context generated during provider
initialisation (see L<provider(7)>).
OSSL_FUNC_digest_freectx() is passed a pointer to the provider side digest context in
the I<dctx> parameter.
This function should free any resources associated with that context.
OSSL_FUNC_digest_dupctx() should duplicate the provider side digest context in the
I<dctx> parameter and return the duplicate copy.
=head2 Digest Generation Functions
OSSL_FUNC_digest_init() initialises a digest operation given a newly created
provider side digest context in the I<dctx> parameter.
The I<params>, if not NULL, should be set on the context in a manner similar to
using OSSL_FUNC_digest_set_ctx_params().
OSSL_FUNC_digest_update() is called to supply data to be digested as part of a
previously initialised digest operation.
The I<dctx> parameter contains a pointer to a previously initialised provider
side context.
OSSL_FUNC_digest_update() should digest I<inl> bytes of data at the location pointed to
by I<in>.
OSSL_FUNC_digest_update() may be called multiple times for a single digest operation.
OSSL_FUNC_digest_final() generates a digest started through previous OSSL_FUNC_digest_init()
and OSSL_FUNC_digest_update() calls.
The I<dctx> parameter contains a pointer to the provider side context.
The digest should be written to I<*out> and the length of the digest to
I<*outl>.
The digest should not exceed I<outsz> bytes.
OSSL_FUNC_digest_digest() is a "oneshot" digest function.
No provider side digest context is used.
Instead the provider context that was created during provider initialisation is
passed in the I<provctx> parameter (see L<provider(7)>).
I<inl> bytes at I<in> should be digested and the result should be stored at
I<out>. The length of the digest should be stored in I<*outl> which should not
exceed I<outsz> bytes.
=head2 Digest Parameters
See L<OSSL_PARAM(3)> for further details on the parameters structure used by
these functions.
OSSL_FUNC_digest_get_params() gets details of the algorithm implementation
and stores them in I<params>.
OSSL_FUNC_digest_set_ctx_params() sets digest operation parameters for the
provider side digest context I<dctx> to I<params>.
Any parameter settings are additional to any that were previously set.
Passing NULL for I<params> should return true.
OSSL_FUNC_digest_get_ctx_params() gets digest operation details details from
the given provider side digest context I<dctx> and stores them in I<params>.
Passing NULL for I<params> should return true.
OSSL_FUNC_digest_gettable_params() returns a constant L<OSSL_PARAM(3)> array
containing descriptors of the parameters that OSSL_FUNC_digest_get_params()
can handle.
OSSL_FUNC_digest_gettable_ctx_params() and
OSSL_FUNC_digest_settable_ctx_params() both return constant
L<OSSL_PARAM(3)> arrays as descriptors of the parameters that
OSSL_FUNC_digest_get_ctx_params() and OSSL_FUNC_digest_set_ctx_params()
can handle, respectively. The array is based on the current state of
the provider side context if I<dctx> is not NULL and on the provider
side algorithm I<provctx> otherwise.
Parameters currently recognised by built-in digests with this function
are as follows. Not all parameters are relevant to, or are understood
by all digests:
=over 4
=item "blocksize" (B<OSSL_DIGEST_PARAM_BLOCK_SIZE>) <unsigned integer>
The digest block size.
The length of the "blocksize" parameter should not exceed that of a B<size_t>.
=item "size" (B<OSSL_DIGEST_PARAM_SIZE>) <unsigned integer>
The digest output size.
The length of the "size" parameter should not exceed that of a B<size_t>.
=item "flags" (B<OSSL_DIGEST_PARAM_FLAGS>) <unsigned integer>
Diverse flags that describe exceptional behaviour for the digest:
=over 4
=item B<EVP_MD_FLAG_ONESHOT>
This digest method can only handle one block of input.
=item B<EVP_MD_FLAG_XOF>
This digest method is an extensible-output function (XOF) and supports
setting the B<OSSL_DIGEST_PARAM_XOFLEN> parameter.
=item B<EVP_MD_FLAG_DIGALGID_NULL>
When setting up a DigestAlgorithmIdentifier, this flag will have the
parameter set to NULL by default. Use this for PKCS#1. I<Note: if
combined with EVP_MD_FLAG_DIGALGID_ABSENT, the latter will override.>
=item B<EVP_MD_FLAG_DIGALGID_ABSENT>
When setting up a DigestAlgorithmIdentifier, this flag will have the
parameter be left absent by default. I<Note: if combined with
EVP_MD_FLAG_DIGALGID_NULL, the latter will be overridden.>
=item B<EVP_MD_FLAG_DIGALGID_CUSTOM>
Custom DigestAlgorithmIdentifier handling via ctrl, with
B<EVP_MD_FLAG_DIGALGID_ABSENT> as default. I<Note: if combined with
EVP_MD_FLAG_DIGALGID_NULL, the latter will be overridden.>
Currently unused.
=back
The length of the "flags" parameter should equal that of an
B<unsigned long int>.
=back
=head2 Digest Context Parameters
OSSL_FUNC_digest_set_ctx_params() sets digest parameters associated with the
given provider side digest context I<dctx> to I<params>.
Any parameter settings are additional to any that were previously set.
See L<OSSL_PARAM(3)> for further details on the parameters structure.
OSSL_FUNC_digest_get_ctx_params() gets details of currently set parameters
values associated with the give provider side digest context I<dctx>
and stores them in I<params>.
See L<OSSL_PARAM(3)> for further details on the parameters structure.
=head1 RETURN VALUES
OSSL_FUNC_digest_newctx() and OSSL_FUNC_digest_dupctx() should return the newly created
provider side digest context, or NULL on failure.
OSSL_FUNC_digest_init(), OSSL_FUNC_digest_update(), OSSL_FUNC_digest_final(), OSSL_FUNC_digest_digest(),
OSSL_FUNC_digest_set_params() and OSSL_FUNC_digest_get_params() should return 1 for success or
0 on error.
OSSL_FUNC_digest_size() should return the digest size.
OSSL_FUNC_digest_block_size() should return the block size of the underlying digest
algorithm.
=head1 BUGS
The EVP_Q_digest(), EVP_Digest() and EVP_DigestFinal_ex() API calls do not
expect the digest size to be larger than EVP_MAX_MD_SIZE. Any algorithm which
produces larger digests is unusable with those API calls.
=head1 SEE ALSO
L<provider(7)>, L<OSSL_PROVIDER-FIPS(7)>, L<OSSL_PROVIDER-default(7)>,
L<OSSL_PROVIDER-legacy(7)>,
L<EVP_MD-common(7)>, L<EVP_MD-BLAKE2(7)>, L<EVP_MD-MD2(7)>,
L<EVP_MD-MD4(7)>, L<EVP_MD-MD5(7)>, L<EVP_MD-MD5-SHA1(7)>,
L<EVP_MD-MDC2(7)>, L<EVP_MD-RIPEMD160(7)>, L<EVP_MD-SHA1(7)>,
L<EVP_MD-SHA2(7)>, L<EVP_MD-SHA3(7)>, L<EVP_MD-SHAKE(7)>,
L<EVP_MD-SM3(7)>, L<EVP_MD-WHIRLPOOL(7)>,
+L<EVP_MD-NULL(7)>,
L<life_cycle-digest(7)>, L<EVP_DigestInit(3)>
=head1 HISTORY
The provider DIGEST interface was introduced in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man7/provider-keymgmt.pod b/doc/man7/provider-keymgmt.pod
index be3a65e31978..c6399b8373b9 100644
--- a/doc/man7/provider-keymgmt.pod
+++ b/doc/man7/provider-keymgmt.pod
@@ -1,422 +1,452 @@
=pod
=head1 NAME
provider-keymgmt - The KEYMGMT library E<lt>-E<gt> provider functions
=head1 SYNOPSIS
#include <openssl/core_dispatch.h>
/*
* None of these are actual functions, but are displayed like this for
* the function signatures for functions that are offered as function
* pointers in OSSL_DISPATCH arrays.
*/
/* Key object (keydata) creation and destruction */
void *OSSL_FUNC_keymgmt_new(void *provctx);
void OSSL_FUNC_keymgmt_free(void *keydata);
/* Generation, a more complex constructor */
void *OSSL_FUNC_keymgmt_gen_init(void *provctx, int selection,
const OSSL_PARAM params[]);
int OSSL_FUNC_keymgmt_gen_set_template(void *genctx, void *template);
int OSSL_FUNC_keymgmt_gen_set_params(void *genctx, const OSSL_PARAM params[]);
const OSSL_PARAM *OSSL_FUNC_keymgmt_gen_settable_params(void *genctx,
void *provctx);
void *OSSL_FUNC_keymgmt_gen(void *genctx, OSSL_CALLBACK *cb, void *cbarg);
void OSSL_FUNC_keymgmt_gen_cleanup(void *genctx);
/* Key loading by object reference, also a constructor */
void *OSSL_FUNC_keymgmt_load(const void *reference, size_t *reference_sz);
/* Key object information */
int OSSL_FUNC_keymgmt_get_params(void *keydata, OSSL_PARAM params[]);
const OSSL_PARAM *OSSL_FUNC_keymgmt_gettable_params(void *provctx);
int OSSL_FUNC_keymgmt_set_params(void *keydata, const OSSL_PARAM params[]);
const OSSL_PARAM *OSSL_FUNC_keymgmt_settable_params(void *provctx);
/* Key object content checks */
int OSSL_FUNC_keymgmt_has(const void *keydata, int selection);
int OSSL_FUNC_keymgmt_match(const void *keydata1, const void *keydata2,
int selection);
/* Discovery of supported operations */
const char *OSSL_FUNC_keymgmt_query_operation_name(int operation_id);
/* Key object import and export functions */
int OSSL_FUNC_keymgmt_import(void *keydata, int selection, const OSSL_PARAM params[]);
const OSSL_PARAM *OSSL_FUNC_keymgmt_import_types(int selection);
int OSSL_FUNC_keymgmt_export(void *keydata, int selection,
OSSL_CALLBACK *param_cb, void *cbarg);
const OSSL_PARAM *OSSL_FUNC_keymgmt_export_types(int selection);
/* Key object duplication, a constructor */
void *OSSL_FUNC_keymgmt_dup(const void *keydata_from, int selection);
/* Key object validation */
int OSSL_FUNC_keymgmt_validate(const void *keydata, int selection, int checktype);
=head1 DESCRIPTION
The KEYMGMT operation doesn't have much public visibility in OpenSSL
libraries, it's rather an internal operation that's designed to work
in tandem with operations that use private/public key pairs.
Because the KEYMGMT operation shares knowledge with the operations it
works with in tandem, they must belong to the same provider.
The OpenSSL libraries will ensure that they do.
The primary responsibility of the KEYMGMT operation is to hold the
provider side key data for the OpenSSL library EVP_PKEY structure.
All "functions" mentioned here are passed as function pointers between
F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
provider_query_operation() function
(see L<provider-base(7)/Provider Functions>).
All these "functions" have a corresponding function type definition
named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
function pointer from a L<OSSL_DISPATCH(3)> element named
B<OSSL_FUNC_{name}>.
For example, the "function" OSSL_FUNC_keymgmt_new() has these:
typedef void *(OSSL_FUNC_keymgmt_new_fn)(void *provctx);
static ossl_inline OSSL_FUNC_keymgmt_new_fn
OSSL_FUNC_keymgmt_new(const OSSL_DISPATCH *opf);
L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
macros in L<openssl-core_dispatch.h(7)>, as follows:
OSSL_FUNC_keymgmt_new OSSL_FUNC_KEYMGMT_NEW
OSSL_FUNC_keymgmt_free OSSL_FUNC_KEYMGMT_FREE
OSSL_FUNC_keymgmt_gen_init OSSL_FUNC_KEYMGMT_GEN_INIT
OSSL_FUNC_keymgmt_gen_set_template OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE
OSSL_FUNC_keymgmt_gen_set_params OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS
OSSL_FUNC_keymgmt_gen_settable_params OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS
OSSL_FUNC_keymgmt_gen OSSL_FUNC_KEYMGMT_GEN
OSSL_FUNC_keymgmt_gen_cleanup OSSL_FUNC_KEYMGMT_GEN_CLEANUP
OSSL_FUNC_keymgmt_load OSSL_FUNC_KEYMGMT_LOAD
OSSL_FUNC_keymgmt_get_params OSSL_FUNC_KEYMGMT_GET_PARAMS
OSSL_FUNC_keymgmt_gettable_params OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS
OSSL_FUNC_keymgmt_set_params OSSL_FUNC_KEYMGMT_SET_PARAMS
OSSL_FUNC_keymgmt_settable_params OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS
OSSL_FUNC_keymgmt_query_operation_name OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME
OSSL_FUNC_keymgmt_has OSSL_FUNC_KEYMGMT_HAS
OSSL_FUNC_keymgmt_validate OSSL_FUNC_KEYMGMT_VALIDATE
OSSL_FUNC_keymgmt_match OSSL_FUNC_KEYMGMT_MATCH
OSSL_FUNC_keymgmt_import OSSL_FUNC_KEYMGMT_IMPORT
OSSL_FUNC_keymgmt_import_types OSSL_FUNC_KEYMGMT_IMPORT_TYPES
OSSL_FUNC_keymgmt_export OSSL_FUNC_KEYMGMT_EXPORT
OSSL_FUNC_keymgmt_export_types OSSL_FUNC_KEYMGMT_EXPORT_TYPES
OSSL_FUNC_keymgmt_dup OSSL_FUNC_KEYMGMT_DUP
=head2 Key Objects
A key object is a collection of data for an asymmetric key, and is
represented as I<keydata> in this manual.
The exact contents of a key object are defined by the provider, and it
is assumed that different operations in one and the same provider use
the exact same structure to represent this collection of data, so that
for example, a key object that has been created using the KEYMGMT
interface that we document here can be passed as is to other provider
operations, such as OP_signature_sign_init() (see
L<provider-signature(7)>).
With some of the KEYMGMT functions, it's possible to select a specific
subset of data to handle, governed by the bits in a I<selection>
indicator. The bits are:
=over 4
=item B<OSSL_KEYMGMT_SELECT_PRIVATE_KEY>
Indicating that the private key data in a key object should be
considered.
=item B<OSSL_KEYMGMT_SELECT_PUBLIC_KEY>
Indicating that the public key data in a key object should be
considered.
=item B<OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS>
Indicating that the domain parameters in a key object should be
considered.
=item B<OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS>
Indicating that other parameters in a key object should be
considered.
Other parameters are key parameters that don't fit any other
classification. In other words, this particular selector bit works as
a last resort bit bucket selector.
=back
Some selector bits have also been combined for easier use:
=over 4
=item B<OSSL_KEYMGMT_SELECT_ALL_PARAMETERS>
Indicating that all key object parameters should be considered,
regardless of their more granular classification.
=for comment This should used by EVP functions such as
EVP_PKEY_copy_parameters() and EVP_PKEY_parameters_eq()
This is a combination of B<OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS> and
B<OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS>.
=for comment If more parameter categories are added, they should be
mentioned here too.
=item B<OSSL_KEYMGMT_SELECT_KEYPAIR>
Indicating that both the whole key pair in a key object should be
considered, i.e. the combination of public and private key.
This is a combination of B<OSSL_KEYMGMT_SELECT_PRIVATE_KEY> and
B<OSSL_KEYMGMT_SELECT_PUBLIC_KEY>.
=item B<OSSL_KEYMGMT_SELECT_ALL>
Indicating that everything in a key object should be considered.
=back
The exact interpretation of those bits or how they combine is left to
each function where you can specify a selector.
It's left to the provider implementation to decide what is reasonable
to do with regards to received selector bits and how to do it.
Among others, an implementation of OSSL_FUNC_keymgmt_match() might opt
to not compare the private half if it has compared the public half,
since a match of one half implies a match of the other half.
=head2 Constructing and Destructing Functions
OSSL_FUNC_keymgmt_new() should create a provider side key object. The
provider context I<provctx> is passed and may be incorporated in the
key object, but that is not mandatory.
OSSL_FUNC_keymgmt_free() should free the passed I<keydata>.
OSSL_FUNC_keymgmt_gen_init(), OSSL_FUNC_keymgmt_gen_set_template(),
OSSL_FUNC_keymgmt_gen_set_params(), OSSL_FUNC_keymgmt_gen_settable_params(),
OSSL_FUNC_keymgmt_gen() and OSSL_FUNC_keymgmt_gen_cleanup() work together as a
more elaborate context based key object constructor.
OSSL_FUNC_keymgmt_gen_init() should create the key object generation context
and initialize it with I<selections>, which will determine what kind
of contents the key object to be generated should get.
The I<params>, if not NULL, should be set on the context in a manner similar to
using OSSL_FUNC_keymgmt_set_params().
OSSL_FUNC_keymgmt_gen_set_template() should add I<template> to the context
I<genctx>. The I<template> is assumed to be a key object constructed
with the same KEYMGMT, and from which content that the implementation
chooses can be used as a template for the key object to be generated.
Typically, the generation of a DSA or DH key would get the domain
parameters from this I<template>.
OSSL_FUNC_keymgmt_gen_set_params() should set additional parameters from
I<params> in the key object generation context I<genctx>.
OSSL_FUNC_keymgmt_gen_settable_params() should return a constant array of
descriptor L<OSSL_PARAM(3)>, for parameters that OSSL_FUNC_keymgmt_gen_set_params()
can handle.
OSSL_FUNC_keymgmt_gen() should perform the key object generation itself, and
return the result. The callback I<cb> should be called at regular
intervals with indications on how the key object generation
progresses.
OSSL_FUNC_keymgmt_gen_cleanup() should clean up and free the key object
generation context I<genctx>
OSSL_FUNC_keymgmt_load() creates a provider side key object based on a
I<reference> object with a size of I<reference_sz> bytes, that only the
provider knows how to interpret, but that may come from other operations.
Outside the provider, this reference is simply an array of bytes.
At least one of OSSL_FUNC_keymgmt_new(), OSSL_FUNC_keymgmt_gen() and
OSSL_FUNC_keymgmt_load() are mandatory, as well as OSSL_FUNC_keymgmt_free() and
OSSL_FUNC_keymgmt_has(). Additionally, if OSSL_FUNC_keymgmt_gen() is present,
OSSL_FUNC_keymgmt_gen_init() and OSSL_FUNC_keymgmt_gen_cleanup() must be
present as well.
=head2 Key Object Information Functions
OSSL_FUNC_keymgmt_get_params() should extract information data associated
with the given I<keydata>, see L</Common Information Parameters>.
OSSL_FUNC_keymgmt_gettable_params() should return a constant array of
descriptor L<OSSL_PARAM(3)>, for parameters that OSSL_FUNC_keymgmt_get_params()
can handle.
If OSSL_FUNC_keymgmt_gettable_params() is present, OSSL_FUNC_keymgmt_get_params()
must also be present, and vice versa.
OSSL_FUNC_keymgmt_set_params() should update information data associated
with the given I<keydata>, see L</Common Information Parameters>.
OSSL_FUNC_keymgmt_settable_params() should return a constant array of
descriptor L<OSSL_PARAM(3)>, for parameters that OSSL_FUNC_keymgmt_set_params()
can handle.
If OSSL_FUNC_keymgmt_settable_params() is present, OSSL_FUNC_keymgmt_set_params()
must also be present, and vice versa.
=head2 Key Object Checking Functions
OSSL_FUNC_keymgmt_query_operation_name() should return the name of the
supported algorithm for the operation I<operation_id>. This is
similar to provider_query_operation() (see L<provider-base(7)>),
but only works as an advisory. If this function is not present, or
returns NULL, the caller is free to assume that there's an algorithm
from the same provider, of the same name as the one used to fetch the
keymgmt and try to use that.
OSSL_FUNC_keymgmt_has() should check whether the given I<keydata> contains the subsets
of data indicated by the I<selector>. A combination of several
selector bits must consider all those subsets, not just one. An
implementation is, however, free to consider an empty subset of data
to still be a valid subset. For algorithms where some selection is
not meaningful such as B<OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS> for
RSA keys the function should just return 1 as the selected subset
is not really missing in the key.
OSSL_FUNC_keymgmt_validate() should check if the I<keydata> contains valid
data subsets indicated by I<selection>. Some combined selections of
data subsets may cause validation of the combined data.
For example, the combination of B<OSSL_KEYMGMT_SELECT_PRIVATE_KEY> and
B<OSSL_KEYMGMT_SELECT_PUBLIC_KEY> (or B<OSSL_KEYMGMT_SELECT_KEYPAIR>
for short) is expected to check that the pairwise consistency of
I<keydata> is valid. The I<checktype> parameter controls what type of check is
performed on the subset of data. Two types of check are defined:
B<OSSL_KEYMGMT_VALIDATE_FULL_CHECK> and B<OSSL_KEYMGMT_VALIDATE_QUICK_CHECK>.
The interpretation of how much checking is performed in a full check versus a
quick check is key type specific. Some providers may have no distinction
between a full check and a quick check. For algorithms where some selection is
not meaningful such as B<OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS> for
RSA keys the function should just return 1 as there is nothing to validate for
that selection.
OSSL_FUNC_keymgmt_match() should check if the data subset indicated by
I<selection> in I<keydata1> and I<keydata2> match. It is assumed that
the caller has ensured that I<keydata1> and I<keydata2> are both owned
by the implementation of this function.
=head2 Key Object Import, Export and Duplication Functions
OSSL_FUNC_keymgmt_import() should import data indicated by I<selection> into
I<keydata> with values taken from the L<OSSL_PARAM(3)> array I<params>.
OSSL_FUNC_keymgmt_export() should extract values indicated by I<selection>
from I<keydata>, create an L<OSSL_PARAM(3)> array with them and call
I<param_cb> with that array as well as the given I<cbarg>.
OSSL_FUNC_keymgmt_import_types() should return a constant array of descriptor
L<OSSL_PARAM(3)> for data indicated by I<selection>, for parameters that
OSSL_FUNC_keymgmt_import() can handle.
OSSL_FUNC_keymgmt_export_types() should return a constant array of descriptor
L<OSSL_PARAM(3)> for data indicated by I<selection>, that the
OSSL_FUNC_keymgmt_export() callback can expect to receive.
OSSL_FUNC_keymgmt_dup() should duplicate data subsets indicated by
I<selection> or the whole key data I<keydata_from> and create a new
provider side key object with the data.
=head2 Common Information Parameters
See L<OSSL_PARAM(3)> for further details on the parameters structure.
Common information parameters currently recognised by all built-in
keymgmt algorithms are as follows:
=over 4
=item "bits" (B<OSSL_PKEY_PARAM_BITS>) <integer>
The value should be the cryptographic length of the cryptosystem to
which the key belongs, in bits. The definition of cryptographic
length is specific to the key cryptosystem.
=item "max-size" (B<OSSL_PKEY_PARAM_MAX_SIZE>) <integer>
The value should be the maximum size that a caller should allocate to
safely store a signature (called I<sig> in L<provider-signature(7)>),
the result of asymmmetric encryption / decryption (I<out> in
L<provider-asym_cipher(7)>, a derived secret (I<secret> in
L<provider-keyexch(7)>, and similar data).
Because an EVP_KEYMGMT method is always tightly bound to another method
(signature, asymmetric cipher, key exchange, ...) and must be of the
same provider, this number only needs to be synchronised with the
dimensions handled in the rest of the same provider.
=item "security-bits" (B<OSSL_PKEY_PARAM_SECURITY_BITS>) <integer>
The value should be the number of security bits of the given key.
Bits of security is defined in SP800-57.
+=item "mandatory-digest" (B<OSSL_PKEY_PARAM_MANDATORY_DIGEST>) <UTF8 string>
+
+If there is a mandatory digest for performing a signature operation with
+keys from this keymgmt, this parameter should get its name as value.
+
+When EVP_PKEY_get_default_digest_name() queries this parameter and it's
+filled in by the implementation, its return value will be 2.
+
+If the keymgmt implementation fills in the value C<""> or C<"UNDEF">,
+L<EVP_PKEY_get_default_digest_name(3)> will place the string C<"UNDEF"> into
+its argument I<mdname>. This signifies that no digest should be specified
+with the corresponding signature operation.
+
+=item "default-digest" (B<OSSL_PKEY_PARAM_DEFAULT_DIGEST>) <UTF8 string>
+
+If there is a default digest for performing a signature operation with
+keys from this keymgmt, this parameter should get its name as value.
+
+When L<EVP_PKEY_get_default_digest_name(3)> queries this parameter and it's
+filled in by the implementation, its return value will be 1. Note that if
+B<OSSL_PKEY_PARAM_MANDATORY_DIGEST> is responded to as well,
+L<EVP_PKEY_get_default_digest_name(3)> ignores the response to this
+parameter.
+
+If the keymgmt implementation fills in the value C<""> or C<"UNDEF">,
+L<EVP_PKEY_get_default_digest_name(3)> will place the string C<"UNDEF"> into
+its argument I<mdname>. This signifies that no digest has to be specified
+with the corresponding signature operation, but may be specified as an
+option.
+
=back
=head1 RETURN VALUES
OSSL_FUNC_keymgmt_new() and OSSL_FUNC_keymgmt_dup() should return a valid
reference to the newly created provider side key object, or NULL on failure.
OSSL_FUNC_keymgmt_import(), OSSL_FUNC_keymgmt_export(), OSSL_FUNC_keymgmt_get_params() and
OSSL_FUNC_keymgmt_set_params() should return 1 for success or 0 on error.
OSSL_FUNC_keymgmt_validate() should return 1 on successful validation, or 0 on
failure.
OSSL_FUNC_keymgmt_has() should return 1 if all the selected data subsets are contained
in the given I<keydata> or 0 otherwise.
OSSL_FUNC_keymgmt_query_operation_name() should return a pointer to a string matching
the requested operation, or NULL if the same name used to fetch the keymgmt
applies.
OSSL_FUNC_keymgmt_gettable_params() and OSSL_FUNC_keymgmt_settable_params()
OSSL_FUNC_keymgmt_import_types(), OSSL_FUNC_keymgmt_export_types()
should
always return a constant L<OSSL_PARAM(3)> array.
=head1 SEE ALSO
L<provider(7)>,
L<EVP_PKEY-X25519(7)>, L<EVP_PKEY-X448(7)>, L<EVP_PKEY-ED25519(7)>,
L<EVP_PKEY-ED448(7)>, L<EVP_PKEY-EC(7)>, L<EVP_PKEY-RSA(7)>,
L<EVP_PKEY-DSA(7)>, L<EVP_PKEY-DH(7)>
=head1 HISTORY
The KEYMGMT interface was introduced in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+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/doc/man7/provider-signature.pod b/doc/man7/provider-signature.pod
index fa38be1b16da..1a9859eac367 100644
--- a/doc/man7/provider-signature.pod
+++ b/doc/man7/provider-signature.pod
@@ -1,439 +1,439 @@
=pod
=head1 NAME
provider-signature - The signature library E<lt>-E<gt> provider functions
=head1 SYNOPSIS
=for openssl multiple includes
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
/*
* None of these are actual functions, but are displayed like this for
* the function signatures for functions that are offered as function
* pointers in OSSL_DISPATCH arrays.
*/
/* Context management */
void *OSSL_FUNC_signature_newctx(void *provctx, const char *propq);
void OSSL_FUNC_signature_freectx(void *ctx);
void *OSSL_FUNC_signature_dupctx(void *ctx);
/* Signing */
int OSSL_FUNC_signature_sign_init(void *ctx, void *provkey,
const OSSL_PARAM params[]);
int OSSL_FUNC_signature_sign(void *ctx, unsigned char *sig, size_t *siglen,
size_t sigsize, const unsigned char *tbs, size_t tbslen);
/* Verifying */
int OSSL_FUNC_signature_verify_init(void *ctx, void *provkey,
const OSSL_PARAM params[]);
int OSSL_FUNC_signature_verify(void *ctx, const unsigned char *sig, size_t siglen,
const unsigned char *tbs, size_t tbslen);
/* Verify Recover */
int OSSL_FUNC_signature_verify_recover_init(void *ctx, void *provkey,
const OSSL_PARAM params[]);
int OSSL_FUNC_signature_verify_recover(void *ctx, unsigned char *rout,
size_t *routlen, size_t routsize,
const unsigned char *sig, size_t siglen);
/* Digest Sign */
int OSSL_FUNC_signature_digest_sign_init(void *ctx, const char *mdname,
void *provkey,
const OSSL_PARAM params[]);
int OSSL_FUNC_signature_digest_sign_update(void *ctx, const unsigned char *data,
size_t datalen);
int OSSL_FUNC_signature_digest_sign_final(void *ctx, unsigned char *sig,
size_t *siglen, size_t sigsize);
int OSSL_FUNC_signature_digest_sign(void *ctx,
unsigned char *sigret, size_t *siglen,
size_t sigsize, const unsigned char *tbs,
size_t tbslen);
/* Digest Verify */
int OSSL_FUNC_signature_digest_verify_init(void *ctx, const char *mdname,
void *provkey,
const OSSL_PARAM params[]);
int OSSL_FUNC_signature_digest_verify_update(void *ctx,
const unsigned char *data,
size_t datalen);
int OSSL_FUNC_signature_digest_verify_final(void *ctx, const unsigned char *sig,
size_t siglen);
int OSSL_FUNC_signature_digest_verify(void *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs,
size_t tbslen);
/* Signature parameters */
int OSSL_FUNC_signature_get_ctx_params(void *ctx, OSSL_PARAM params[]);
const OSSL_PARAM *OSSL_FUNC_signature_gettable_ctx_params(void *ctx,
void *provctx);
int OSSL_FUNC_signature_set_ctx_params(void *ctx, const OSSL_PARAM params[]);
const OSSL_PARAM *OSSL_FUNC_signature_settable_ctx_params(void *ctx,
void *provctx);
/* MD parameters */
int OSSL_FUNC_signature_get_ctx_md_params(void *ctx, OSSL_PARAM params[]);
const OSSL_PARAM * OSSL_FUNC_signature_gettable_ctx_md_params(void *ctx);
int OSSL_FUNC_signature_set_ctx_md_params(void *ctx, const OSSL_PARAM params[]);
const OSSL_PARAM * OSSL_FUNC_signature_settable_ctx_md_params(void *ctx);
=head1 DESCRIPTION
This documentation is primarily aimed at provider authors. See L<provider(7)>
for further information.
The signature (OSSL_OP_SIGNATURE) operation enables providers to implement
signature algorithms and make them available to applications via the API
functions L<EVP_PKEY_sign(3)>,
L<EVP_PKEY_verify(3)>,
and L<EVP_PKEY_verify_recover(3)> (as well
as other related functions).
All "functions" mentioned here are passed as function pointers between
F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays via
L<OSSL_ALGORITHM(3)> arrays that are returned by the provider's
provider_query_operation() function
(see L<provider-base(7)/Provider Functions>).
All these "functions" have a corresponding function type definition
named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
function pointer from an L<OSSL_DISPATCH(3)> element named
B<OSSL_FUNC_{name}>.
For example, the "function" OSSL_FUNC_signature_newctx() has these:
typedef void *(OSSL_FUNC_signature_newctx_fn)(void *provctx, const char *propq);
static ossl_inline OSSL_FUNC_signature_newctx_fn
OSSL_FUNC_signature_newctx(const OSSL_DISPATCH *opf);
L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
macros in L<openssl-core_dispatch.h(7)>, as follows:
OSSL_FUNC_signature_newctx OSSL_FUNC_SIGNATURE_NEWCTX
OSSL_FUNC_signature_freectx OSSL_FUNC_SIGNATURE_FREECTX
OSSL_FUNC_signature_dupctx OSSL_FUNC_SIGNATURE_DUPCTX
OSSL_FUNC_signature_sign_init OSSL_FUNC_SIGNATURE_SIGN_INIT
OSSL_FUNC_signature_sign OSSL_FUNC_SIGNATURE_SIGN
OSSL_FUNC_signature_verify_init OSSL_FUNC_SIGNATURE_VERIFY_INIT
OSSL_FUNC_signature_verify OSSL_FUNC_SIGNATURE_VERIFY
OSSL_FUNC_signature_verify_recover_init OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT
OSSL_FUNC_signature_verify_recover OSSL_FUNC_SIGNATURE_VERIFY_RECOVER
OSSL_FUNC_signature_digest_sign_init OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT
OSSL_FUNC_signature_digest_sign_update OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE
OSSL_FUNC_signature_digest_sign_final OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL
OSSL_FUNC_signature_digest_sign OSSL_FUNC_SIGNATURE_DIGEST_SIGN
OSSL_FUNC_signature_digest_verify_init OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT
OSSL_FUNC_signature_digest_verify_update OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE
OSSL_FUNC_signature_digest_verify_final OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL
OSSL_FUNC_signature_digest_verify OSSL_FUNC_SIGNATURE_DIGEST_VERIFY
OSSL_FUNC_signature_get_ctx_params OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS
OSSL_FUNC_signature_gettable_ctx_params OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS
OSSL_FUNC_signature_set_ctx_params OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS
OSSL_FUNC_signature_settable_ctx_params OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS
OSSL_FUNC_signature_get_ctx_md_params OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS
OSSL_FUNC_signature_gettable_ctx_md_params OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS
OSSL_FUNC_signature_set_ctx_md_params OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS
OSSL_FUNC_signature_settable_ctx_md_params OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS
A signature algorithm implementation may not implement all of these functions.
In order to be a consistent set of functions we must have at least a set of
context functions (OSSL_FUNC_signature_newctx and OSSL_FUNC_signature_freectx) as well as a
set of "signature" functions, i.e. at least one of:
=over 4
=item OSSL_FUNC_signature_sign_init and OSSL_FUNC_signature_sign
=item OSSL_FUNC_signature_verify_init and OSSL_FUNC_signature_verify
-=item OSSL_FUNC_signature_verify_recover_init and OSSL_FUNC_signature_verify_init
+=item OSSL_FUNC_signature_verify_recover_init and OSSL_FUNC_signature_verify_recover
=item OSSL_FUNC_signature_digest_sign_init, OSSL_FUNC_signature_digest_sign_update and OSSL_FUNC_signature_digest_sign_final
=item OSSL_FUNC_signature_digest_verify_init, OSSL_FUNC_signature_digest_verify_update and OSSL_FUNC_signature_digest_verify_final
=item OSSL_FUNC_signature_digest_sign_init and OSSL_FUNC_signature_digest_sign
=item OSSL_FUNC_signature_digest_verify_init and OSSL_FUNC_signature_digest_verify
=back
OSSL_FUNC_signature_set_ctx_params and OSSL_FUNC_signature_settable_ctx_params are optional,
but if one of them is present then the other one must also be present. The same
applies to OSSL_FUNC_signature_get_ctx_params and OSSL_FUNC_signature_gettable_ctx_params, as
well as the "md_params" functions. The OSSL_FUNC_signature_dupctx function is optional.
A signature algorithm must also implement some mechanism for generating,
loading or importing keys via the key management (OSSL_OP_KEYMGMT) operation.
See L<provider-keymgmt(7)> for further details.
=head2 Context Management Functions
OSSL_FUNC_signature_newctx() should create and return a pointer to a provider side
structure for holding context information during a signature operation.
A pointer to this context will be passed back in a number of the other signature
operation function calls.
The parameter I<provctx> is the provider context generated during provider
initialisation (see L<provider(7)>). The I<propq> parameter is a property query
string that may be (optionally) used by the provider during any "fetches" that
it may perform (if it performs any).
OSSL_FUNC_signature_freectx() is passed a pointer to the provider side signature
context in the I<ctx> parameter.
This function should free any resources associated with that context.
OSSL_FUNC_signature_dupctx() should duplicate the provider side signature context in
the I<ctx> parameter and return the duplicate copy.
=head2 Signing Functions
OSSL_FUNC_signature_sign_init() initialises a context for signing given a provider side
signature context in the I<ctx> parameter, and a pointer to a provider key object
in the I<provkey> parameter.
The I<params>, if not NULL, should be set on the context in a manner similar to
using OSSL_FUNC_signature_set_ctx_params().
The key object should have been previously generated, loaded or imported into
the provider using the key management (OSSL_OP_KEYMGMT) operation (see
provider-keymgmt(7)>.
OSSL_FUNC_signature_sign() performs the actual signing itself.
A previously initialised signature context is passed in the I<ctx>
parameter.
The data to be signed is pointed to be the I<tbs> parameter which is I<tbslen>
bytes long.
Unless I<sig> is NULL, the signature should be written to the location pointed
to by the I<sig> parameter and it should not exceed I<sigsize> bytes in length.
The length of the signature should be written to I<*siglen>.
If I<sig> is NULL then the maximum length of the signature should be written to
I<*siglen>.
=head2 Verify Functions
OSSL_FUNC_signature_verify_init() initialises a context for verifying a signature given
a provider side signature context in the I<ctx> parameter, and a pointer to a
provider key object in the I<provkey> parameter.
The I<params>, if not NULL, should be set on the context in a manner similar to
using OSSL_FUNC_signature_set_ctx_params().
The key object should have been previously generated, loaded or imported into
the provider using the key management (OSSL_OP_KEYMGMT) operation (see
provider-keymgmt(7)>.
OSSL_FUNC_signature_verify() performs the actual verification itself.
A previously initialised signature context is passed in the I<ctx> parameter.
The data that the signature covers is pointed to be the I<tbs> parameter which
is I<tbslen> bytes long.
The signature is pointed to by the I<sig> parameter which is I<siglen> bytes
long.
=head2 Verify Recover Functions
OSSL_FUNC_signature_verify_recover_init() initialises a context for recovering the
signed data given a provider side signature context in the I<ctx> parameter, and
a pointer to a provider key object in the I<provkey> parameter.
The I<params>, if not NULL, should be set on the context in a manner similar to
using OSSL_FUNC_signature_set_ctx_params().
The key object should have been previously generated, loaded or imported into
the provider using the key management (OSSL_OP_KEYMGMT) operation (see
provider-keymgmt(7)>.
OSSL_FUNC_signature_verify_recover() performs the actual verify recover itself.
A previously initialised signature context is passed in the I<ctx> parameter.
The signature is pointed to by the I<sig> parameter which is I<siglen> bytes
long.
Unless I<rout> is NULL, the recovered data should be written to the location
pointed to by I<rout> which should not exceed I<routsize> bytes in length.
The length of the recovered data should be written to I<*routlen>.
If I<rout> is NULL then the maximum size of the output buffer is written to
the I<routlen> parameter.
=head2 Digest Sign Functions
OSSL_FUNC_signature_digeset_sign_init() initialises a context for signing given a
provider side signature context in the I<ctx> parameter, and a pointer to a
provider key object in the I<provkey> parameter.
The I<params>, if not NULL, should be set on the context in a manner similar to
using OSSL_FUNC_signature_set_ctx_params() and
OSSL_FUNC_signature_set_ctx_md_params().
The key object should have been
previously generated, loaded or imported into the provider using the
key management (OSSL_OP_KEYMGMT) operation (see provider-keymgmt(7)>.
The name of the digest to be used will be in the I<mdname> parameter.
OSSL_FUNC_signature_digest_sign_update() provides data to be signed in the I<data>
parameter which should be of length I<datalen>. A previously initialised
signature context is passed in the I<ctx> parameter. This function may be called
multiple times to cumulatively add data to be signed.
OSSL_FUNC_signature_digest_sign_final() finalises a signature operation previously
started through OSSL_FUNC_signature_digest_sign_init() and
OSSL_FUNC_signature_digest_sign_update() calls. Once finalised no more data will be
added through OSSL_FUNC_signature_digest_sign_update(). A previously initialised
signature context is passed in the I<ctx> parameter. Unless I<sig> is NULL, the
signature should be written to the location pointed to by the I<sig> parameter
and it should not exceed I<sigsize> bytes in length. The length of the signature
should be written to I<*siglen>. If I<sig> is NULL then the maximum length of
the signature should be written to I<*siglen>.
OSSL_FUNC_signature_digest_sign() implements a "one shot" digest sign operation
previously started through OSSL_FUNC_signature_digeset_sign_init(). A previously
initialised signature context is passed in the I<ctx> parameter. The data to be
signed is in I<tbs> which should be I<tbslen> bytes long. Unless I<sig> is NULL,
the signature should be written to the location pointed to by the I<sig>
parameter and it should not exceed I<sigsize> bytes in length. The length of the
signature should be written to I<*siglen>. If I<sig> is NULL then the maximum
length of the signature should be written to I<*siglen>.
=head2 Digest Verify Functions
OSSL_FUNC_signature_digeset_verify_init() initialises a context for verifying given a
provider side verification context in the I<ctx> parameter, and a pointer to a
provider key object in the I<provkey> parameter.
The I<params>, if not NULL, should be set on the context in a manner similar to
OSSL_FUNC_signature_set_ctx_params() and
OSSL_FUNC_signature_set_ctx_md_params().
The key object should have been
previously generated, loaded or imported into the provider using the
key management (OSSL_OP_KEYMGMT) operation (see provider-keymgmt(7)>.
The name of the digest to be used will be in the I<mdname> parameter.
OSSL_FUNC_signature_digest_verify_update() provides data to be verified in the I<data>
parameter which should be of length I<datalen>. A previously initialised
verification context is passed in the I<ctx> parameter. This function may be
called multiple times to cumulatively add data to be verified.
OSSL_FUNC_signature_digest_verify_final() finalises a verification operation previously
started through OSSL_FUNC_signature_digest_verify_init() and
OSSL_FUNC_signature_digest_verify_update() calls. Once finalised no more data will be
added through OSSL_FUNC_signature_digest_verify_update(). A previously initialised
verification context is passed in the I<ctx> parameter. The signature to be
verified is in I<sig> which is I<siglen> bytes long.
OSSL_FUNC_signature_digest_verify() implements a "one shot" digest verify operation
previously started through OSSL_FUNC_signature_digeset_verify_init(). A previously
initialised verification context is passed in the I<ctx> parameter. The data to be
verified is in I<tbs> which should be I<tbslen> bytes long. The signature to be
verified is in I<sig> which is I<siglen> bytes long.
=head2 Signature parameters
See L<OSSL_PARAM(3)> for further details on the parameters structure used by
the OSSL_FUNC_signature_get_ctx_params() and OSSL_FUNC_signature_set_ctx_params() functions.
OSSL_FUNC_signature_get_ctx_params() gets signature parameters associated with the
given provider side signature context I<ctx> and stored them in I<params>.
Passing NULL for I<params> should return true.
OSSL_FUNC_signature_set_ctx_params() sets the signature parameters associated with the
given provider side signature context I<ctx> to I<params>.
Any parameter settings are additional to any that were previously set.
Passing NULL for I<params> should return true.
Common parameters currently recognised by built-in signature algorithms are as
follows.
=over 4
=item "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <UTF8 string>
Get or sets the name of the digest algorithm used for the input to the
signature functions. It is required in order to calculate the "algorithm-id".
=item "properties" (B<OSSL_SIGNATURE_PARAM_PROPERTIES>) <UTF8 string>
Sets the name of the property query associated with the "digest" algorithm.
NULL is used if this optional value is not set.
=item "digest-size" (B<OSSL_SIGNATURE_PARAM_DIGEST_SIZE>) <unsigned integer>
Gets or sets the output size of the digest algorithm used for the input to the
signature functions.
The length of the "digest-size" parameter should not exceed that of a B<size_t>.
=item "algorithm-id" (B<OSSL_SIGNATURE_PARAM_ALGORITHM_ID>) <octet string>
Gets the DER encoded AlgorithmIdentifier that corresponds to the combination of
signature algorithm and digest algorithm for the signature operation.
=item "kat" (B<OSSL_SIGNATURE_PARAM_KAT>) <unsigned integer>
Sets a flag to modify the sign operation to return an error if the initial
calculated signature is invalid.
In the normal mode of operation - new random values are chosen until the
signature operation succeeds.
By default it retries until a signature is calculated.
Setting the value to 0 causes the sign operation to retry,
otherwise the sign operation is only tried once and returns whether or not it
was successful.
Known answer tests can be performed if the random generator is overridden to
supply known values that either pass or fail.
=back
OSSL_FUNC_signature_gettable_ctx_params() and OSSL_FUNC_signature_settable_ctx_params() get a
constant L<OSSL_PARAM(3)> array that describes the gettable and settable parameters,
i.e. parameters that can be used with OSSL_FUNC_signature_get_ctx_params() and
OSSL_FUNC_signature_set_ctx_params() respectively.
=head2 MD parameters
See L<OSSL_PARAM(3)> for further details on the parameters structure used by
the OSSL_FUNC_signature_get_md_ctx_params() and OSSL_FUNC_signature_set_md_ctx_params()
functions.
OSSL_FUNC_signature_get_md_ctx_params() gets digest parameters associated with the
given provider side digest signature context I<ctx> and stores them in I<params>.
Passing NULL for I<params> should return true.
OSSL_FUNC_signature_set_ms_ctx_params() sets the digest parameters associated with the
given provider side digest signature context I<ctx> to I<params>.
Any parameter settings are additional to any that were previously set.
Passing NULL for I<params> should return true.
Parameters currently recognised by built-in signature algorithms are the same
as those for built-in digest algorithms. See
L<provider-digest(7)/Digest Parameters> for further information.
OSSL_FUNC_signature_gettable_md_ctx_params() and OSSL_FUNC_signature_settable_md_ctx_params()
get a constant L<OSSL_PARAM(3)> array that describes the gettable and settable
digest parameters, i.e. parameters that can be used with
OSSL_FUNC_signature_get_md_ctx_params() and OSSL_FUNC_signature_set_md_ctx_params()
respectively.
=head1 RETURN VALUES
OSSL_FUNC_signature_newctx() and OSSL_FUNC_signature_dupctx() should return the newly created
-provider side signature, or NULL on failure.
+provider side signature context, or NULL on failure.
OSSL_FUNC_signature_gettable_ctx_params(), OSSL_FUNC_signature_settable_ctx_params(),
OSSL_FUNC_signature_gettable_md_ctx_params() and OSSL_FUNC_signature_settable_md_ctx_params(),
return the gettable or settable parameters in a constant L<OSSL_PARAM(3)> array.
All other functions should return 1 for success or 0 on error.
=head1 SEE ALSO
L<provider(7)>
=head1 HISTORY
The provider SIGNATURE interface was introduced in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+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/engines/e_padlock.c b/engines/e_padlock.c
index 9ad1c48c71a5..7e0cfc21fc9b 100644
--- a/engines/e_padlock.c
+++ b/engines/e_padlock.c
@@ -1,752 +1,763 @@
/*
- * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-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 uses the low level AES and engine functions (which are deprecated
* for non-internal use) in order to implement the padlock engine AES ciphers.
*/
#define OPENSSL_SUPPRESS_DEPRECATED
#include <stdio.h>
#include <string.h>
#include <openssl/opensslconf.h>
#include <openssl/crypto.h>
#include <openssl/engine.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/modes.h>
#ifndef OPENSSL_NO_PADLOCKENG
/*
* VIA PadLock AES is available *ONLY* on some x86 CPUs. Not only that it
* doesn't exist elsewhere, but it even can't be compiled on other platforms!
*/
# undef COMPILE_PADLOCKENG
# if defined(PADLOCK_ASM)
# define COMPILE_PADLOCKENG
# ifdef OPENSSL_NO_DYNAMIC_ENGINE
static ENGINE *ENGINE_padlock(void);
# endif
# endif
# ifdef OPENSSL_NO_DYNAMIC_ENGINE
void engine_load_padlock_int(void);
void engine_load_padlock_int(void)
{
/* On non-x86 CPUs it just returns. */
# ifdef COMPILE_PADLOCKENG
ENGINE *toadd = ENGINE_padlock();
if (!toadd)
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
}
# endif
# ifdef COMPILE_PADLOCKENG
/* Function for ENGINE detection and control */
static int padlock_available(void);
static int padlock_init(ENGINE *e);
/* RNG Stuff */
static RAND_METHOD padlock_rand;
/* Cipher Stuff */
static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
const int **nids, int nid);
/* Engine names */
static const char *padlock_id = "padlock";
static char padlock_name[100];
/* Available features */
static int padlock_use_ace = 0; /* Advanced Cryptography Engine */
static int padlock_use_rng = 0; /* Random Number Generator */
/* ===== Engine "management" functions ===== */
/* Prepare the ENGINE structure for registration */
static int padlock_bind_helper(ENGINE *e)
{
/* Check available features */
padlock_available();
/*
* RNG is currently disabled for reasons discussed in commentary just
* before padlock_rand_bytes function.
*/
padlock_use_rng = 0;
/* Generate a nice engine name with available features */
BIO_snprintf(padlock_name, sizeof(padlock_name),
"VIA PadLock (%s, %s)",
padlock_use_rng ? "RNG" : "no-RNG",
padlock_use_ace ? "ACE" : "no-ACE");
/* Register everything or return with an error */
if (!ENGINE_set_id(e, padlock_id) ||
!ENGINE_set_name(e, padlock_name) ||
!ENGINE_set_init_function(e, padlock_init) ||
(padlock_use_ace && !ENGINE_set_ciphers(e, padlock_ciphers)) ||
(padlock_use_rng && !ENGINE_set_RAND(e, &padlock_rand))) {
return 0;
}
/* Everything looks good */
return 1;
}
# ifdef OPENSSL_NO_DYNAMIC_ENGINE
/* Constructor */
static ENGINE *ENGINE_padlock(void)
{
ENGINE *eng = ENGINE_new();
if (eng == NULL) {
return NULL;
}
if (!padlock_bind_helper(eng)) {
ENGINE_free(eng);
return NULL;
}
return eng;
}
# endif
/* Check availability of the engine */
static int padlock_init(ENGINE *e)
{
return (padlock_use_rng || padlock_use_ace);
}
+# ifndef AES_ASM
+static int padlock_aes_set_encrypt_key(const unsigned char *userKey,
+ const int bits,
+ AES_KEY *key);
+static int padlock_aes_set_decrypt_key(const unsigned char *userKey,
+ const int bits,
+ AES_KEY *key);
+# define AES_ASM
+# define AES_set_encrypt_key padlock_aes_set_encrypt_key
+# define AES_set_decrypt_key padlock_aes_set_decrypt_key
+# include "../crypto/aes/aes_core.c"
+# endif
+
/*
* This stuff is needed if this ENGINE is being compiled into a
* self-contained shared-library.
*/
# ifndef OPENSSL_NO_DYNAMIC_ENGINE
static int padlock_bind_fn(ENGINE *e, const char *id)
{
if (id && (strcmp(id, padlock_id) != 0)) {
return 0;
}
if (!padlock_bind_helper(e)) {
return 0;
}
return 1;
}
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(padlock_bind_fn)
# endif /* !OPENSSL_NO_DYNAMIC_ENGINE */
/* ===== Here comes the "real" engine ===== */
/* Some AES-related constants */
# define AES_BLOCK_SIZE 16
# define AES_KEY_SIZE_128 16
# define AES_KEY_SIZE_192 24
# define AES_KEY_SIZE_256 32
/*
* Here we store the status information relevant to the current context.
*/
/*
* BIG FAT WARNING: Inline assembler in PADLOCK_XCRYPT_ASM() depends on
* the order of items in this structure. Don't blindly modify, reorder,
* etc!
*/
struct padlock_cipher_data {
unsigned char iv[AES_BLOCK_SIZE]; /* Initialization vector */
union {
unsigned int pad[4];
struct {
int rounds:4;
int dgst:1; /* n/a in C3 */
int align:1; /* n/a in C3 */
int ciphr:1; /* n/a in C3 */
unsigned int keygen:1;
int interm:1;
unsigned int encdec:1;
int ksize:2;
} b;
} cword; /* Control word */
AES_KEY ks; /* Encryption key */
};
/* Interface to assembler module */
unsigned int padlock_capability(void);
void padlock_key_bswap(AES_KEY *key);
void padlock_verify_context(struct padlock_cipher_data *ctx);
void padlock_reload_key(void);
void padlock_aes_block(void *out, const void *inp,
struct padlock_cipher_data *ctx);
int padlock_ecb_encrypt(void *out, const void *inp,
struct padlock_cipher_data *ctx, size_t len);
int padlock_cbc_encrypt(void *out, const void *inp,
struct padlock_cipher_data *ctx, size_t len);
int padlock_cfb_encrypt(void *out, const void *inp,
struct padlock_cipher_data *ctx, size_t len);
int padlock_ofb_encrypt(void *out, const void *inp,
struct padlock_cipher_data *ctx, size_t len);
int padlock_ctr32_encrypt(void *out, const void *inp,
struct padlock_cipher_data *ctx, size_t len);
int padlock_xstore(void *out, int edx);
void padlock_sha1_oneshot(void *ctx, const void *inp, size_t len);
void padlock_sha1(void *ctx, const void *inp, size_t len);
void padlock_sha256_oneshot(void *ctx, const void *inp, size_t len);
void padlock_sha256(void *ctx, const void *inp, size_t len);
/*
* Load supported features of the CPU to see if the PadLock is available.
*/
static int padlock_available(void)
{
unsigned int edx = padlock_capability();
/* Fill up some flags */
padlock_use_ace = ((edx & (0x3 << 6)) == (0x3 << 6));
padlock_use_rng = ((edx & (0x3 << 2)) == (0x3 << 2));
return padlock_use_ace + padlock_use_rng;
}
/* ===== AES encryption/decryption ===== */
# if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb)
# define NID_aes_128_cfb NID_aes_128_cfb128
# endif
# if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb)
# define NID_aes_128_ofb NID_aes_128_ofb128
# endif
# if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb)
# define NID_aes_192_cfb NID_aes_192_cfb128
# endif
# if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb)
# define NID_aes_192_ofb NID_aes_192_ofb128
# endif
# if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb)
# define NID_aes_256_cfb NID_aes_256_cfb128
# endif
# if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb)
# define NID_aes_256_ofb NID_aes_256_ofb128
# endif
/* List of supported ciphers. */
static const int padlock_cipher_nids[] = {
NID_aes_128_ecb,
NID_aes_128_cbc,
NID_aes_128_cfb,
NID_aes_128_ofb,
NID_aes_128_ctr,
NID_aes_192_ecb,
NID_aes_192_cbc,
NID_aes_192_cfb,
NID_aes_192_ofb,
NID_aes_192_ctr,
NID_aes_256_ecb,
NID_aes_256_cbc,
NID_aes_256_cfb,
NID_aes_256_ofb,
NID_aes_256_ctr
};
static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids) /
sizeof(padlock_cipher_nids[0]));
/* Function prototypes ... */
static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
# define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) + \
( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F ) )
# define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\
NEAREST_ALIGNED(EVP_CIPHER_CTX_get_cipher_data(ctx)))
static int
padlock_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
const unsigned char *in_arg, size_t nbytes)
{
return padlock_ecb_encrypt(out_arg, in_arg,
ALIGNED_CIPHER_DATA(ctx), nbytes);
}
static int
padlock_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
const unsigned char *in_arg, size_t nbytes)
{
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
int ret;
memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE);
if ((ret = padlock_cbc_encrypt(out_arg, in_arg, cdata, nbytes)))
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE);
return ret;
}
static int
padlock_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
const unsigned char *in_arg, size_t nbytes)
{
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
size_t chunk;
if ((chunk = EVP_CIPHER_CTX_get_num(ctx))) { /* borrow chunk variable */
unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx);
if (chunk >= AES_BLOCK_SIZE)
return 0; /* bogus value */
if (EVP_CIPHER_CTX_is_encrypting(ctx))
while (chunk < AES_BLOCK_SIZE && nbytes != 0) {
ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk];
chunk++, nbytes--;
} else
while (chunk < AES_BLOCK_SIZE && nbytes != 0) {
unsigned char c = *(in_arg++);
*(out_arg++) = c ^ ivp[chunk];
ivp[chunk++] = c, nbytes--;
}
EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE);
}
if (nbytes == 0)
return 1;
memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE);
if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) {
if (!padlock_cfb_encrypt(out_arg, in_arg, cdata, chunk))
return 0;
nbytes -= chunk;
}
if (nbytes) {
unsigned char *ivp = cdata->iv;
out_arg += chunk;
in_arg += chunk;
EVP_CIPHER_CTX_set_num(ctx, nbytes);
if (cdata->cword.b.encdec) {
cdata->cword.b.encdec = 0;
padlock_reload_key();
padlock_aes_block(ivp, ivp, cdata);
cdata->cword.b.encdec = 1;
padlock_reload_key();
while (nbytes) {
unsigned char c = *(in_arg++);
*(out_arg++) = c ^ *ivp;
*(ivp++) = c, nbytes--;
}
} else {
padlock_reload_key();
padlock_aes_block(ivp, ivp, cdata);
padlock_reload_key();
while (nbytes) {
*ivp = *(out_arg++) = *(in_arg++) ^ *ivp;
ivp++, nbytes--;
}
}
}
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE);
return 1;
}
static int
padlock_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
const unsigned char *in_arg, size_t nbytes)
{
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
size_t chunk;
/*
* ctx->num is maintained in byte-oriented modes, such as CFB and OFB...
*/
if ((chunk = EVP_CIPHER_CTX_get_num(ctx))) { /* borrow chunk variable */
unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx);
if (chunk >= AES_BLOCK_SIZE)
return 0; /* bogus value */
while (chunk < AES_BLOCK_SIZE && nbytes != 0) {
*(out_arg++) = *(in_arg++) ^ ivp[chunk];
chunk++, nbytes--;
}
EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE);
}
if (nbytes == 0)
return 1;
memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE);
if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) {
if (!padlock_ofb_encrypt(out_arg, in_arg, cdata, chunk))
return 0;
nbytes -= chunk;
}
if (nbytes) {
unsigned char *ivp = cdata->iv;
out_arg += chunk;
in_arg += chunk;
EVP_CIPHER_CTX_set_num(ctx, nbytes);
padlock_reload_key(); /* empirically found */
padlock_aes_block(ivp, ivp, cdata);
padlock_reload_key(); /* empirically found */
while (nbytes) {
*(out_arg++) = *(in_arg++) ^ *ivp;
ivp++, nbytes--;
}
}
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE);
return 1;
}
static void padlock_ctr32_encrypt_glue(const unsigned char *in,
unsigned char *out, size_t blocks,
struct padlock_cipher_data *ctx,
const unsigned char *ivec)
{
memcpy(ctx->iv, ivec, AES_BLOCK_SIZE);
padlock_ctr32_encrypt(out, in, ctx, AES_BLOCK_SIZE * blocks);
}
static int
padlock_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
const unsigned char *in_arg, size_t nbytes)
{
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
int n = EVP_CIPHER_CTX_get_num(ctx);
unsigned int num;
if (n < 0)
return 0;
num = (unsigned int)n;
CRYPTO_ctr128_encrypt_ctr32(in_arg, out_arg, nbytes,
cdata, EVP_CIPHER_CTX_iv_noconst(ctx),
EVP_CIPHER_CTX_buf_noconst(ctx), &num,
(ctr128_f) padlock_ctr32_encrypt_glue);
EVP_CIPHER_CTX_set_num(ctx, (size_t)num);
return 1;
}
# define EVP_CIPHER_block_size_ECB AES_BLOCK_SIZE
# define EVP_CIPHER_block_size_CBC AES_BLOCK_SIZE
# define EVP_CIPHER_block_size_OFB 1
# define EVP_CIPHER_block_size_CFB 1
# define EVP_CIPHER_block_size_CTR 1
/*
* Declaring so many ciphers by hand would be a pain. Instead introduce a bit
* of preprocessor magic :-)
*/
# define DECLARE_AES_EVP(ksize,lmode,umode) \
static EVP_CIPHER *_hidden_aes_##ksize##_##lmode = NULL; \
static const EVP_CIPHER *padlock_aes_##ksize##_##lmode(void) \
{ \
if (_hidden_aes_##ksize##_##lmode == NULL \
&& ((_hidden_aes_##ksize##_##lmode = \
EVP_CIPHER_meth_new(NID_aes_##ksize##_##lmode, \
EVP_CIPHER_block_size_##umode, \
AES_KEY_SIZE_##ksize)) == NULL \
|| !EVP_CIPHER_meth_set_iv_length(_hidden_aes_##ksize##_##lmode, \
AES_BLOCK_SIZE) \
|| !EVP_CIPHER_meth_set_flags(_hidden_aes_##ksize##_##lmode, \
0 | EVP_CIPH_##umode##_MODE) \
|| !EVP_CIPHER_meth_set_init(_hidden_aes_##ksize##_##lmode, \
padlock_aes_init_key) \
|| !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_##ksize##_##lmode, \
padlock_##lmode##_cipher) \
|| !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_##ksize##_##lmode, \
sizeof(struct padlock_cipher_data) + 16) \
|| !EVP_CIPHER_meth_set_set_asn1_params(_hidden_aes_##ksize##_##lmode, \
EVP_CIPHER_set_asn1_iv) \
|| !EVP_CIPHER_meth_set_get_asn1_params(_hidden_aes_##ksize##_##lmode, \
EVP_CIPHER_get_asn1_iv))) { \
EVP_CIPHER_meth_free(_hidden_aes_##ksize##_##lmode); \
_hidden_aes_##ksize##_##lmode = NULL; \
} \
return _hidden_aes_##ksize##_##lmode; \
}
DECLARE_AES_EVP(128, ecb, ECB)
DECLARE_AES_EVP(128, cbc, CBC)
DECLARE_AES_EVP(128, cfb, CFB)
DECLARE_AES_EVP(128, ofb, OFB)
DECLARE_AES_EVP(128, ctr, CTR)
DECLARE_AES_EVP(192, ecb, ECB)
DECLARE_AES_EVP(192, cbc, CBC)
DECLARE_AES_EVP(192, cfb, CFB)
DECLARE_AES_EVP(192, ofb, OFB)
DECLARE_AES_EVP(192, ctr, CTR)
DECLARE_AES_EVP(256, ecb, ECB)
DECLARE_AES_EVP(256, cbc, CBC)
DECLARE_AES_EVP(256, cfb, CFB)
DECLARE_AES_EVP(256, ofb, OFB)
DECLARE_AES_EVP(256, ctr, CTR)
static int
padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids,
int nid)
{
/* No specific cipher => return a list of supported nids ... */
if (!cipher) {
*nids = padlock_cipher_nids;
return padlock_cipher_nids_num;
}
/* ... or the requested "cipher" otherwise */
switch (nid) {
case NID_aes_128_ecb:
*cipher = padlock_aes_128_ecb();
break;
case NID_aes_128_cbc:
*cipher = padlock_aes_128_cbc();
break;
case NID_aes_128_cfb:
*cipher = padlock_aes_128_cfb();
break;
case NID_aes_128_ofb:
*cipher = padlock_aes_128_ofb();
break;
case NID_aes_128_ctr:
*cipher = padlock_aes_128_ctr();
break;
case NID_aes_192_ecb:
*cipher = padlock_aes_192_ecb();
break;
case NID_aes_192_cbc:
*cipher = padlock_aes_192_cbc();
break;
case NID_aes_192_cfb:
*cipher = padlock_aes_192_cfb();
break;
case NID_aes_192_ofb:
*cipher = padlock_aes_192_ofb();
break;
case NID_aes_192_ctr:
*cipher = padlock_aes_192_ctr();
break;
case NID_aes_256_ecb:
*cipher = padlock_aes_256_ecb();
break;
case NID_aes_256_cbc:
*cipher = padlock_aes_256_cbc();
break;
case NID_aes_256_cfb:
*cipher = padlock_aes_256_cfb();
break;
case NID_aes_256_ofb:
*cipher = padlock_aes_256_ofb();
break;
case NID_aes_256_ctr:
*cipher = padlock_aes_256_ctr();
break;
default:
/* Sorry, we don't support this NID */
*cipher = NULL;
return 0;
}
return 1;
}
/* Prepare the encryption key for PadLock usage */
static int
padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
struct padlock_cipher_data *cdata;
int key_len = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
unsigned long mode = EVP_CIPHER_CTX_get_mode(ctx);
if (key == NULL)
return 0; /* ERROR */
cdata = ALIGNED_CIPHER_DATA(ctx);
memset(cdata, 0, sizeof(*cdata));
/* Prepare Control word. */
if (mode == EVP_CIPH_OFB_MODE || mode == EVP_CIPH_CTR_MODE)
cdata->cword.b.encdec = 0;
else
cdata->cword.b.encdec = (EVP_CIPHER_CTX_is_encrypting(ctx) == 0);
cdata->cword.b.rounds = 10 + (key_len - 128) / 32;
cdata->cword.b.ksize = (key_len - 128) / 64;
switch (key_len) {
case 128:
/*
* PadLock can generate an extended key for AES128 in hardware
*/
memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128);
cdata->cword.b.keygen = 0;
break;
case 192:
case 256:
/*
* Generate an extended AES key in software. Needed for AES192/AES256
*/
/*
* Well, the above applies to Stepping 8 CPUs and is listed as
* hardware errata. They most likely will fix it at some point and
* then a check for stepping would be due here.
*/
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
&& !enc)
AES_set_decrypt_key(key, key_len, &cdata->ks);
else
AES_set_encrypt_key(key, key_len, &cdata->ks);
-# ifndef AES_ASM
/*
* OpenSSL C functions use byte-swapped extended key.
*/
padlock_key_bswap(&cdata->ks);
-# endif
cdata->cword.b.keygen = 1;
break;
default:
/* ERROR */
return 0;
}
/*
* This is done to cover for cases when user reuses the
* context for new key. The catch is that if we don't do
* this, padlock_eas_cipher might proceed with old key...
*/
padlock_reload_key();
return 1;
}
/* ===== Random Number Generator ===== */
/*
* This code is not engaged. The reason is that it does not comply
* with recommendations for VIA RNG usage for secure applications
* (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it
* provide meaningful error control...
*/
/*
* Wrapper that provides an interface between the API and the raw PadLock
* RNG
*/
static int padlock_rand_bytes(unsigned char *output, int count)
{
unsigned int eax, buf;
while (count >= 8) {
eax = padlock_xstore(output, 0);
if (!(eax & (1 << 6)))
return 0; /* RNG disabled */
/* this ---vv--- covers DC bias, Raw Bits and String Filter */
if (eax & (0x1F << 10))
return 0;
if ((eax & 0x1F) == 0)
continue; /* no data, retry... */
if ((eax & 0x1F) != 8)
return 0; /* fatal failure... */
output += 8;
count -= 8;
}
while (count > 0) {
eax = padlock_xstore(&buf, 3);
if (!(eax & (1 << 6)))
return 0; /* RNG disabled */
/* this ---vv--- covers DC bias, Raw Bits and String Filter */
if (eax & (0x1F << 10))
return 0;
if ((eax & 0x1F) == 0)
continue; /* no data, retry... */
if ((eax & 0x1F) != 1)
return 0; /* fatal failure... */
*output++ = (unsigned char)buf;
count--;
}
OPENSSL_cleanse(&buf, sizeof(buf));
return 1;
}
/* Dummy but necessary function */
static int padlock_rand_status(void)
{
return 1;
}
/* Prepare structure for registration */
static RAND_METHOD padlock_rand = {
NULL, /* seed */
padlock_rand_bytes, /* bytes */
NULL, /* cleanup */
NULL, /* add */
padlock_rand_bytes, /* pseudorand */
padlock_rand_status, /* rand status */
};
# endif /* COMPILE_PADLOCKENG */
#endif /* !OPENSSL_NO_PADLOCKENG */
#if defined(OPENSSL_NO_PADLOCKENG) || !defined(COMPILE_PADLOCKENG)
# ifndef OPENSSL_NO_DYNAMIC_ENGINE
OPENSSL_EXPORT
int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns);
OPENSSL_EXPORT
int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns)
{
return 0;
}
IMPLEMENT_DYNAMIC_CHECK_FN()
# endif
#endif
diff --git a/include/crypto/bn.h b/include/crypto/bn.h
index 390e5ac07c2b..fd1c09d997de 100644
--- a/include/crypto/bn.h
+++ b/include/crypto/bn.h
@@ -1,123 +1,117 @@
/*
* Copyright 2014-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_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_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);
#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;
-int ossl_bn_rsa_do_unblind(const BIGNUM *intermediate,
- const BN_BLINDING *blinding,
- const BIGNUM *possible_arg2,
- const BIGNUM *to_mod, BN_CTX *ctx,
- unsigned char *buf, int num);
-
#endif
diff --git a/include/crypto/cmperr.h b/include/crypto/cmperr.h
index ac61dd4875c2..2bd163738466 100644
--- a/include/crypto/cmperr.h
+++ b/include/crypto/cmperr.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-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_CMPERR_H
# define OSSL_CRYPTO_CMPERR_H
# pragma once
# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
# ifdef __cplusplus
extern "C" {
# endif
# ifndef OPENSSL_NO_CMP
int ossl_err_load_CMP_strings(void);
# endif
# ifdef __cplusplus
}
# endif
#endif
diff --git a/include/crypto/dsaerr.h b/include/crypto/dsaerr.h
index 9898097d0dd1..fde8358fc96d 100644
--- a/include/crypto/dsaerr.h
+++ b/include/crypto/dsaerr.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-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_DSAERR_H
# define OSSL_CRYPTO_DSAERR_H
# pragma once
# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
# ifdef __cplusplus
extern "C" {
# endif
# ifndef OPENSSL_NO_DSA
int ossl_err_load_DSA_strings(void);
# endif
# ifdef __cplusplus
}
# endif
#endif
diff --git a/include/crypto/ecerr.h b/include/crypto/ecerr.h
index 4658ae8fb2cd..782526bf8565 100644
--- a/include/crypto/ecerr.h
+++ b/include/crypto/ecerr.h
@@ -1,30 +1,30 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
#ifndef OSSL_CRYPTO_ECERR_H
# define OSSL_CRYPTO_ECERR_H
# pragma once
# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
# ifdef __cplusplus
extern "C" {
# endif
# ifndef OPENSSL_NO_EC
int ossl_err_load_EC_strings(void);
# endif
# ifdef __cplusplus
}
# endif
#endif
diff --git a/include/internal/refcount.h b/include/internal/refcount.h
index 7412d62f56fd..3392d3b490d5 100644
--- a/include/internal/refcount.h
+++ b/include/internal/refcount.h
@@ -1,178 +1,178 @@
/*
- * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
#ifndef OSSL_INTERNAL_REFCOUNT_H
# define OSSL_INTERNAL_REFCOUNT_H
# pragma once
# include <openssl/e_os2.h>
# include <openssl/trace.h>
-# ifndef OPENSSL_DEV_NO_ATOMICS
+# if defined(OPENSSL_THREADS) && !defined(OPENSSL_DEV_NO_ATOMICS)
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
&& !defined(__STDC_NO_ATOMICS__)
# include <stdatomic.h>
# define HAVE_C11_ATOMICS
# endif
# if defined(HAVE_C11_ATOMICS) && defined(ATOMIC_INT_LOCK_FREE) \
&& ATOMIC_INT_LOCK_FREE > 0
# define HAVE_ATOMICS 1
typedef _Atomic int CRYPTO_REF_COUNT;
static inline int CRYPTO_UP_REF(_Atomic int *val, int *ret,
ossl_unused void *lock)
{
*ret = atomic_fetch_add_explicit(val, 1, memory_order_relaxed) + 1;
return 1;
}
/*
* Changes to shared structure other than reference counter have to be
* serialized. And any kind of serialization implies a release fence. This
* means that by the time reference counter is decremented all other
* changes are visible on all processors. Hence decrement itself can be
* relaxed. In case it hits zero, object will be destructed. Since it's
* last use of the object, destructor programmer might reason that access
* to mutable members doesn't have to be serialized anymore, which would
* otherwise imply an acquire fence. Hence conditional acquire fence...
*/
static inline int CRYPTO_DOWN_REF(_Atomic int *val, int *ret,
ossl_unused void *lock)
{
*ret = atomic_fetch_sub_explicit(val, 1, memory_order_relaxed) - 1;
if (*ret == 0)
atomic_thread_fence(memory_order_acquire);
return 1;
}
# elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) && __GCC_ATOMIC_INT_LOCK_FREE > 0
# define HAVE_ATOMICS 1
typedef int CRYPTO_REF_COUNT;
static __inline__ int CRYPTO_UP_REF(int *val, int *ret, ossl_unused void *lock)
{
*ret = __atomic_fetch_add(val, 1, __ATOMIC_RELAXED) + 1;
return 1;
}
static __inline__ int CRYPTO_DOWN_REF(int *val, int *ret,
ossl_unused void *lock)
{
*ret = __atomic_fetch_sub(val, 1, __ATOMIC_RELAXED) - 1;
if (*ret == 0)
__atomic_thread_fence(__ATOMIC_ACQUIRE);
return 1;
}
# elif defined(__ICL) && defined(_WIN32)
# define HAVE_ATOMICS 1
typedef volatile int CRYPTO_REF_COUNT;
static __inline int CRYPTO_UP_REF(volatile int *val, int *ret,
ossl_unused void *lock)
{
*ret = _InterlockedExchangeAdd((void *)val, 1) + 1;
return 1;
}
static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret,
ossl_unused void *lock)
{
*ret = _InterlockedExchangeAdd((void *)val, -1) - 1;
return 1;
}
# elif defined(_MSC_VER) && _MSC_VER>=1200
# define HAVE_ATOMICS 1
typedef volatile int CRYPTO_REF_COUNT;
# if (defined(_M_ARM) && _M_ARM>=7 && !defined(_WIN32_WCE)) || defined(_M_ARM64)
# include <intrin.h>
# if defined(_M_ARM64) && !defined(_ARM_BARRIER_ISH)
# define _ARM_BARRIER_ISH _ARM64_BARRIER_ISH
# endif
static __inline int CRYPTO_UP_REF(volatile int *val, int *ret,
ossl_unused void *lock)
{
*ret = _InterlockedExchangeAdd_nf(val, 1) + 1;
return 1;
}
static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret,
ossl_unused void *lock)
{
*ret = _InterlockedExchangeAdd_nf(val, -1) - 1;
if (*ret == 0)
__dmb(_ARM_BARRIER_ISH);
return 1;
}
# else
# if !defined(_WIN32_WCE)
# pragma intrinsic(_InterlockedExchangeAdd)
# else
# if _WIN32_WCE >= 0x600
extern long __cdecl _InterlockedExchangeAdd(long volatile*, long);
# else
/* under Windows CE we still have old-style Interlocked* functions */
extern long __cdecl InterlockedExchangeAdd(long volatile*, long);
# define _InterlockedExchangeAdd InterlockedExchangeAdd
# endif
# endif
static __inline int CRYPTO_UP_REF(volatile int *val, int *ret,
ossl_unused void *lock)
{
*ret = _InterlockedExchangeAdd(val, 1) + 1;
return 1;
}
static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret,
ossl_unused void *lock)
{
*ret = _InterlockedExchangeAdd(val, -1) - 1;
return 1;
}
# endif
# endif
# endif /* !OPENSSL_DEV_NO_ATOMICS */
/*
* All the refcounting implementations above define HAVE_ATOMICS, so if it's
* still undefined here (such as when OPENSSL_DEV_NO_ATOMICS is defined), it
* means we need to implement a fallback. This fallback uses locks.
*/
# ifndef HAVE_ATOMICS
typedef int CRYPTO_REF_COUNT;
# define CRYPTO_UP_REF(val, ret, lock) CRYPTO_atomic_add(val, 1, ret, lock)
# define CRYPTO_DOWN_REF(val, ret, lock) CRYPTO_atomic_add(val, -1, ret, lock)
# endif
# if !defined(NDEBUG) && !defined(OPENSSL_NO_STDIO)
# define REF_ASSERT_ISNT(test) \
(void)((test) ? (OPENSSL_die("refcount error", __FILE__, __LINE__), 1) : 0)
# else
# define REF_ASSERT_ISNT(i)
# endif
# define REF_PRINT_EX(text, count, object) \
OSSL_TRACE3(REF_COUNT, "%p:%4d:%s\n", (object), (count), (text));
# define REF_PRINT_COUNT(text, object) \
REF_PRINT_EX(text, object->references, (void *)object)
#endif
diff --git a/include/openssl/cmp.h.in b/include/openssl/cmp.h.in
index f05cb3e54851..fb5ae6717f8e 100644
--- a/include/openssl/cmp.h.in
+++ b/include/openssl/cmp.h.in
@@ -1,477 +1,478 @@
/*
* {- join("\n * ", @autowarntext) -}
*
- * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
{-
use OpenSSL::stackhash qw(generate_stack_macros);
-}
#ifndef OPENSSL_CMP_H
# define OPENSSL_CMP_H
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_CMP
# include <openssl/crmf.h>
# include <openssl/cmperr.h>
# include <openssl/cmp_util.h>
# include <openssl/http.h>
/* explicit #includes not strictly needed since implied by the above: */
# include <openssl/types.h>
# include <openssl/safestack.h>
# include <openssl/x509.h>
# include <openssl/x509v3.h>
# ifdef __cplusplus
extern "C" {
# endif
# define OSSL_CMP_PVNO 2
/*-
* PKIFailureInfo ::= BIT STRING {
* -- since we can fail in more than one way!
* -- More codes may be added in the future if/when required.
* badAlg (0),
* -- unrecognized or unsupported Algorithm Identifier
* badMessageCheck (1),
* -- integrity check failed (e.g., signature did not verify)
* badRequest (2),
* -- transaction not permitted or supported
* badTime (3),
* -- messageTime was not sufficiently close to the system time,
* -- as defined by local policy
* badCertId (4),
* -- no certificate could be found matching the provided criteria
* badDataFormat (5),
* -- the data submitted has the wrong format
* wrongAuthority (6),
* -- the authority indicated in the request is different from the
* -- one creating the response token
* incorrectData (7),
* -- the requester's data is incorrect (for notary services)
* missingTimeStamp (8),
* -- when the timestamp is missing but should be there
* -- (by policy)
* badPOP (9),
* -- the proof-of-possession failed
* certRevoked (10),
* -- the certificate has already been revoked
* certConfirmed (11),
* -- the certificate has already been confirmed
* wrongIntegrity (12),
* -- invalid integrity, password based instead of signature or
* -- vice versa
* badRecipientNonce (13),
* -- invalid recipient nonce, either missing or wrong value
* timeNotAvailable (14),
* -- the TSA's time source is not available
* unacceptedPolicy (15),
* -- the requested TSA policy is not supported by the TSA.
* unacceptedExtension (16),
* -- the requested extension is not supported by the TSA.
* addInfoNotAvailable (17),
* -- the additional information requested could not be
* -- understood or is not available
* badSenderNonce (18),
* -- invalid sender nonce, either missing or wrong size
* badCertTemplate (19),
* -- invalid cert. template or missing mandatory information
* signerNotTrusted (20),
* -- signer of the message unknown or not trusted
* transactionIdInUse (21),
* -- the transaction identifier is already in use
* unsupportedVersion (22),
* -- the version of the message is not supported
* notAuthorized (23),
* -- the sender was not authorized to make the preceding
* -- request or perform the preceding action
* systemUnavail (24),
* -- the request cannot be handled due to system unavailability
* systemFailure (25),
* -- the request cannot be handled due to system failure
* duplicateCertReq (26)
* -- certificate cannot be issued because a duplicate
* -- certificate already exists
* }
*/
# define OSSL_CMP_PKIFAILUREINFO_badAlg 0
# define OSSL_CMP_PKIFAILUREINFO_badMessageCheck 1
# define OSSL_CMP_PKIFAILUREINFO_badRequest 2
# define OSSL_CMP_PKIFAILUREINFO_badTime 3
# define OSSL_CMP_PKIFAILUREINFO_badCertId 4
# define OSSL_CMP_PKIFAILUREINFO_badDataFormat 5
# define OSSL_CMP_PKIFAILUREINFO_wrongAuthority 6
# define OSSL_CMP_PKIFAILUREINFO_incorrectData 7
# define OSSL_CMP_PKIFAILUREINFO_missingTimeStamp 8
# define OSSL_CMP_PKIFAILUREINFO_badPOP 9
# define OSSL_CMP_PKIFAILUREINFO_certRevoked 10
# define OSSL_CMP_PKIFAILUREINFO_certConfirmed 11
# define OSSL_CMP_PKIFAILUREINFO_wrongIntegrity 12
# define OSSL_CMP_PKIFAILUREINFO_badRecipientNonce 13
# define OSSL_CMP_PKIFAILUREINFO_timeNotAvailable 14
# define OSSL_CMP_PKIFAILUREINFO_unacceptedPolicy 15
# define OSSL_CMP_PKIFAILUREINFO_unacceptedExtension 16
# define OSSL_CMP_PKIFAILUREINFO_addInfoNotAvailable 17
# define OSSL_CMP_PKIFAILUREINFO_badSenderNonce 18
# define OSSL_CMP_PKIFAILUREINFO_badCertTemplate 19
# define OSSL_CMP_PKIFAILUREINFO_signerNotTrusted 20
# define OSSL_CMP_PKIFAILUREINFO_transactionIdInUse 21
# define OSSL_CMP_PKIFAILUREINFO_unsupportedVersion 22
# define OSSL_CMP_PKIFAILUREINFO_notAuthorized 23
# define OSSL_CMP_PKIFAILUREINFO_systemUnavail 24
# define OSSL_CMP_PKIFAILUREINFO_systemFailure 25
# define OSSL_CMP_PKIFAILUREINFO_duplicateCertReq 26
# define OSSL_CMP_PKIFAILUREINFO_MAX 26
# define OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN \
((1 << (OSSL_CMP_PKIFAILUREINFO_MAX + 1)) - 1)
# if OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN > INT_MAX
# error CMP_PKIFAILUREINFO_MAX bit pattern does not fit in type int
# endif
typedef ASN1_BIT_STRING OSSL_CMP_PKIFAILUREINFO;
# define OSSL_CMP_CTX_FAILINFO_badAlg (1 << 0)
# define OSSL_CMP_CTX_FAILINFO_badMessageCheck (1 << 1)
# define OSSL_CMP_CTX_FAILINFO_badRequest (1 << 2)
# define OSSL_CMP_CTX_FAILINFO_badTime (1 << 3)
# define OSSL_CMP_CTX_FAILINFO_badCertId (1 << 4)
# define OSSL_CMP_CTX_FAILINFO_badDataFormat (1 << 5)
# define OSSL_CMP_CTX_FAILINFO_wrongAuthority (1 << 6)
# define OSSL_CMP_CTX_FAILINFO_incorrectData (1 << 7)
# define OSSL_CMP_CTX_FAILINFO_missingTimeStamp (1 << 8)
# define OSSL_CMP_CTX_FAILINFO_badPOP (1 << 9)
# define OSSL_CMP_CTX_FAILINFO_certRevoked (1 << 10)
# define OSSL_CMP_CTX_FAILINFO_certConfirmed (1 << 11)
# define OSSL_CMP_CTX_FAILINFO_wrongIntegrity (1 << 12)
# define OSSL_CMP_CTX_FAILINFO_badRecipientNonce (1 << 13)
# define OSSL_CMP_CTX_FAILINFO_timeNotAvailable (1 << 14)
# define OSSL_CMP_CTX_FAILINFO_unacceptedPolicy (1 << 15)
# define OSSL_CMP_CTX_FAILINFO_unacceptedExtension (1 << 16)
# define OSSL_CMP_CTX_FAILINFO_addInfoNotAvailable (1 << 17)
# define OSSL_CMP_CTX_FAILINFO_badSenderNonce (1 << 18)
# define OSSL_CMP_CTX_FAILINFO_badCertTemplate (1 << 19)
# define OSSL_CMP_CTX_FAILINFO_signerNotTrusted (1 << 20)
# define OSSL_CMP_CTX_FAILINFO_transactionIdInUse (1 << 21)
# define OSSL_CMP_CTX_FAILINFO_unsupportedVersion (1 << 22)
# define OSSL_CMP_CTX_FAILINFO_notAuthorized (1 << 23)
# define OSSL_CMP_CTX_FAILINFO_systemUnavail (1 << 24)
# define OSSL_CMP_CTX_FAILINFO_systemFailure (1 << 25)
# define OSSL_CMP_CTX_FAILINFO_duplicateCertReq (1 << 26)
/*-
* PKIStatus ::= INTEGER {
* accepted (0),
* -- you got exactly what you asked for
* grantedWithMods (1),
* -- you got something like what you asked for; the
* -- requester is responsible for ascertaining the differences
* rejection (2),
* -- you don't get it, more information elsewhere in the message
* waiting (3),
* -- the request body part has not yet been processed; expect to
* -- hear more later (note: proper handling of this status
* -- response MAY use the polling req/rep PKIMessages specified
* -- in Section 5.3.22; alternatively, polling in the underlying
* -- transport layer MAY have some utility in this regard)
* revocationWarning (4),
* -- this message contains a warning that a revocation is
* -- imminent
* revocationNotification (5),
* -- notification that a revocation has occurred
* keyUpdateWarning (6)
* -- update already done for the oldCertId specified in
* -- CertReqMsg
* }
*/
# define OSSL_CMP_PKISTATUS_request -3
# define OSSL_CMP_PKISTATUS_trans -2
# define OSSL_CMP_PKISTATUS_unspecified -1
# define OSSL_CMP_PKISTATUS_accepted 0
# define OSSL_CMP_PKISTATUS_grantedWithMods 1
# define OSSL_CMP_PKISTATUS_rejection 2
# define OSSL_CMP_PKISTATUS_waiting 3
# define OSSL_CMP_PKISTATUS_revocationWarning 4
# define OSSL_CMP_PKISTATUS_revocationNotification 5
# define OSSL_CMP_PKISTATUS_keyUpdateWarning 6
typedef ASN1_INTEGER OSSL_CMP_PKISTATUS;
DECLARE_ASN1_ITEM(OSSL_CMP_PKISTATUS)
# define OSSL_CMP_CERTORENCCERT_CERTIFICATE 0
# define OSSL_CMP_CERTORENCCERT_ENCRYPTEDCERT 1
/* data type declarations */
typedef struct ossl_cmp_ctx_st OSSL_CMP_CTX;
typedef struct ossl_cmp_pkiheader_st OSSL_CMP_PKIHEADER;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKIHEADER)
typedef struct ossl_cmp_msg_st OSSL_CMP_MSG;
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_MSG)
DECLARE_ASN1_ENCODE_FUNCTIONS(OSSL_CMP_MSG, OSSL_CMP_MSG, OSSL_CMP_MSG)
typedef struct ossl_cmp_certstatus_st OSSL_CMP_CERTSTATUS;
{-
generate_stack_macros("OSSL_CMP_CERTSTATUS");
-}
typedef struct ossl_cmp_itav_st OSSL_CMP_ITAV;
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV)
{-
generate_stack_macros("OSSL_CMP_ITAV");
-}
typedef struct ossl_cmp_revrepcontent_st OSSL_CMP_REVREPCONTENT;
typedef struct ossl_cmp_pkisi_st OSSL_CMP_PKISI;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKISI)
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_PKISI)
{-
generate_stack_macros("OSSL_CMP_PKISI");
-}
typedef struct ossl_cmp_certrepmessage_st OSSL_CMP_CERTREPMESSAGE;
{-
generate_stack_macros("OSSL_CMP_CERTREPMESSAGE");
-}
typedef struct ossl_cmp_pollrep_st OSSL_CMP_POLLREP;
typedef STACK_OF(OSSL_CMP_POLLREP) OSSL_CMP_POLLREPCONTENT;
typedef struct ossl_cmp_certresponse_st OSSL_CMP_CERTRESPONSE;
{-
generate_stack_macros("OSSL_CMP_CERTRESPONSE");
-}
typedef STACK_OF(ASN1_UTF8STRING) OSSL_CMP_PKIFREETEXT;
/*
* function DECLARATIONS
*/
/* from cmp_asn.c */
OSSL_CMP_ITAV *OSSL_CMP_ITAV_create(ASN1_OBJECT *type, ASN1_TYPE *value);
void OSSL_CMP_ITAV_set0(OSSL_CMP_ITAV *itav, ASN1_OBJECT *type,
ASN1_TYPE *value);
ASN1_OBJECT *OSSL_CMP_ITAV_get0_type(const OSSL_CMP_ITAV *itav);
ASN1_TYPE *OSSL_CMP_ITAV_get0_value(const OSSL_CMP_ITAV *itav);
int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
OSSL_CMP_ITAV *itav);
void OSSL_CMP_ITAV_free(OSSL_CMP_ITAV *itav);
void OSSL_CMP_MSG_free(OSSL_CMP_MSG *msg);
/* from cmp_ctx.c */
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);
/* CMP general options: */
# define OSSL_CMP_OPT_LOG_VERBOSITY 0
/* CMP transfer options: */
# define OSSL_CMP_OPT_KEEP_ALIVE 10
# define OSSL_CMP_OPT_MSG_TIMEOUT 11
# define OSSL_CMP_OPT_TOTAL_TIMEOUT 12
/* CMP request options: */
# define OSSL_CMP_OPT_VALIDITY_DAYS 20
# define OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT 21
# define OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL 22
# define OSSL_CMP_OPT_POLICIES_CRITICAL 23
# define OSSL_CMP_OPT_POPO_METHOD 24
# define OSSL_CMP_OPT_IMPLICIT_CONFIRM 25
# define OSSL_CMP_OPT_DISABLE_CONFIRM 26
# define OSSL_CMP_OPT_REVOCATION_REASON 27
/* CMP protection options: */
# define OSSL_CMP_OPT_UNPROTECTED_SEND 30
# define OSSL_CMP_OPT_UNPROTECTED_ERRORS 31
# define OSSL_CMP_OPT_OWF_ALGNID 32
# define OSSL_CMP_OPT_MAC_ALGNID 33
# define OSSL_CMP_OPT_DIGEST_ALGNID 34
# define OSSL_CMP_OPT_IGNORE_KEYUSAGE 35
# define OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR 36
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);
/* CMP-specific callback for logging and outputting the error queue: */
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) \
OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_LOG_VERBOSITY, 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, OSSL_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,
- const 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);
# define OSSL_CMP_PKISI_BUFLEN 1024
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);
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);
/* from cmp_status.c */
char *OSSL_CMP_CTX_snprint_PKIStatus(const OSSL_CMP_CTX *ctx, char *buf,
size_t bufsize);
char *OSSL_CMP_snprint_PKIStatusInfo(const OSSL_CMP_PKISI *statusInfo,
char *buf, size_t bufsize);
OSSL_CMP_PKISI *
OSSL_CMP_STATUSINFO_new(int status, int fail_info, const char *text);
/* from cmp_hdr.c */
ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const
OSSL_CMP_PKIHEADER *hdr);
ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr);
/* from cmp_msg.c */
OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg);
int OSSL_CMP_MSG_get_bodytype(const OSSL_CMP_MSG *msg);
int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+int OSSL_CMP_MSG_update_recipNonce(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid);
OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file, OSSL_LIB_CTX *libctx,
const char *propq);
int OSSL_CMP_MSG_write(const char *file, const OSSL_CMP_MSG *msg);
OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg);
int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg);
/* from cmp_vfy.c */
int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg);
int OSSL_CMP_validate_cert_path(const OSSL_CMP_CTX *ctx,
X509_STORE *trusted_store, X509 *cert);
/* from cmp_http.c */
OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *req);
/* from cmp_server.c */
typedef struct ossl_cmp_srv_ctx_st OSSL_CMP_SRV_CTX;
OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req);
OSSL_CMP_MSG * OSSL_CMP_CTX_server_perform(OSSL_CMP_CTX *client_ctx,
const OSSL_CMP_MSG *req);
OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(OSSL_LIB_CTX *libctx, const char *propq);
void OSSL_CMP_SRV_CTX_free(OSSL_CMP_SRV_CTX *srv_ctx);
typedef OSSL_CMP_PKISI *(*OSSL_CMP_SRV_cert_request_cb_t)
(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req, int certReqId,
const OSSL_CRMF_MSG *crm, const X509_REQ *p10cr,
X509 **certOut, STACK_OF(X509) **chainOut, STACK_OF(X509) **caPubs);
typedef OSSL_CMP_PKISI *(*OSSL_CMP_SRV_rr_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req,
const X509_NAME *issuer,
const ASN1_INTEGER *serial);
typedef int (*OSSL_CMP_SRV_genm_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req,
const STACK_OF(OSSL_CMP_ITAV) *in,
STACK_OF(OSSL_CMP_ITAV) **out);
typedef void (*OSSL_CMP_SRV_error_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req,
const OSSL_CMP_PKISI *statusInfo,
const ASN1_INTEGER *errorCode,
const OSSL_CMP_PKIFREETEXT *errDetails);
typedef int (*OSSL_CMP_SRV_certConf_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req,
int certReqId,
const ASN1_OCTET_STRING *certHash,
const OSSL_CMP_PKISI *si);
typedef int (*OSSL_CMP_SRV_pollReq_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req, int certReqId,
OSSL_CMP_MSG **certReq,
int64_t *check_after);
int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
OSSL_CMP_SRV_cert_request_cb_t process_cert_request,
OSSL_CMP_SRV_rr_cb_t process_rr,
OSSL_CMP_SRV_genm_cb_t process_genm,
OSSL_CMP_SRV_error_cb_t process_error,
OSSL_CMP_SRV_certConf_cb_t process_certConf,
OSSL_CMP_SRV_pollReq_cb_t process_pollReq);
OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx);
void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx);
int OSSL_CMP_SRV_CTX_set_send_unprotected_errors(OSSL_CMP_SRV_CTX *srv_ctx,
int val);
int OSSL_CMP_SRV_CTX_set_accept_unprotected(OSSL_CMP_SRV_CTX *srv_ctx, int val);
int OSSL_CMP_SRV_CTX_set_accept_raverified(OSSL_CMP_SRV_CTX *srv_ctx, int val);
int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx,
int val);
/* from cmp_client.c */
X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type,
const OSSL_CRMF_MSG *crm);
# define OSSL_CMP_IR 0
# define OSSL_CMP_CR 2
# define OSSL_CMP_P10CR 4
# define OSSL_CMP_KUR 7
# define OSSL_CMP_exec_IR_ses(ctx) \
OSSL_CMP_exec_certreq(ctx, OSSL_CMP_IR, NULL)
# define OSSL_CMP_exec_CR_ses(ctx) \
OSSL_CMP_exec_certreq(ctx, OSSL_CMP_CR, NULL)
# define OSSL_CMP_exec_P10CR_ses(ctx) \
OSSL_CMP_exec_certreq(ctx, OSSL_CMP_P10CR, NULL)
# define OSSL_CMP_exec_KUR_ses(ctx) \
OSSL_CMP_exec_certreq(ctx, OSSL_CMP_KUR, NULL)
int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type,
const OSSL_CRMF_MSG *crm, int *checkAfter);
int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx);
STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx);
# ifdef __cplusplus
}
# endif
# endif /* !defined(OPENSSL_NO_CMP) */
#endif /* !defined(OPENSSL_CMP_H) */
diff --git a/include/openssl/cmperr.h b/include/openssl/cmperr.h
index 06e9dbff363d..49fd5e392a17 100644
--- a/include/openssl/cmperr.h
+++ b/include/openssl/cmperr.h
@@ -1,114 +1,116 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
#ifndef OPENSSL_CMPERR_H
# define OPENSSL_CMPERR_H
# pragma once
# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
# include <openssl/cryptoerr_legacy.h>
# ifndef OPENSSL_NO_CMP
/*
* CMP reason codes.
*/
# define CMP_R_ALGORITHM_NOT_SUPPORTED 139
# define CMP_R_BAD_CHECKAFTER_IN_POLLREP 167
# define CMP_R_BAD_REQUEST_ID 108
# define CMP_R_CERTHASH_UNMATCHED 156
# define CMP_R_CERTID_NOT_FOUND 109
# define CMP_R_CERTIFICATE_NOT_ACCEPTED 169
# define CMP_R_CERTIFICATE_NOT_FOUND 112
# define CMP_R_CERTREQMSG_NOT_FOUND 157
# define CMP_R_CERTRESPONSE_NOT_FOUND 113
# define CMP_R_CERT_AND_KEY_DO_NOT_MATCH 114
# define CMP_R_CHECKAFTER_OUT_OF_RANGE 181
# define CMP_R_ENCOUNTERED_KEYUPDATEWARNING 176
# define CMP_R_ENCOUNTERED_WAITING 162
# define CMP_R_ERROR_CALCULATING_PROTECTION 115
# define CMP_R_ERROR_CREATING_CERTCONF 116
# define CMP_R_ERROR_CREATING_CERTREP 117
# define CMP_R_ERROR_CREATING_CERTREQ 163
# define CMP_R_ERROR_CREATING_ERROR 118
# define CMP_R_ERROR_CREATING_GENM 119
# define CMP_R_ERROR_CREATING_GENP 120
# define CMP_R_ERROR_CREATING_PKICONF 122
# define CMP_R_ERROR_CREATING_POLLREP 123
# define CMP_R_ERROR_CREATING_POLLREQ 124
# define CMP_R_ERROR_CREATING_RP 125
# define CMP_R_ERROR_CREATING_RR 126
# define CMP_R_ERROR_PARSING_PKISTATUS 107
# define CMP_R_ERROR_PROCESSING_MESSAGE 158
# define CMP_R_ERROR_PROTECTING_MESSAGE 127
# define CMP_R_ERROR_SETTING_CERTHASH 128
# define CMP_R_ERROR_UNEXPECTED_CERTCONF 160
# define CMP_R_ERROR_VALIDATING_PROTECTION 140
# define CMP_R_ERROR_VALIDATING_SIGNATURE 171
# define CMP_R_FAILED_BUILDING_OWN_CHAIN 164
# define CMP_R_FAILED_EXTRACTING_PUBKEY 141
# define CMP_R_FAILURE_OBTAINING_RANDOM 110
# define CMP_R_FAIL_INFO_OUT_OF_RANGE 129
# define CMP_R_INVALID_ARGS 100
# define CMP_R_INVALID_OPTION 174
# define CMP_R_MISSING_CERTID 165
# define CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION 130
# define CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE 142
# define CMP_R_MISSING_P10CSR 121
# define CMP_R_MISSING_PBM_SECRET 166
# define CMP_R_MISSING_PRIVATE_KEY 131
+# define CMP_R_MISSING_PRIVATE_KEY_FOR_POPO 190
# define CMP_R_MISSING_PROTECTION 143
+# define CMP_R_MISSING_PUBLIC_KEY 183
# define CMP_R_MISSING_REFERENCE_CERT 168
# define CMP_R_MISSING_SECRET 178
# define CMP_R_MISSING_SENDER_IDENTIFICATION 111
# define CMP_R_MISSING_TRUST_ANCHOR 179
# define CMP_R_MISSING_TRUST_STORE 144
# define CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED 161
# define CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED 170
# define CMP_R_MULTIPLE_SAN_SOURCES 102
# define CMP_R_NO_STDIO 194
# define CMP_R_NO_SUITABLE_SENDER_CERT 145
# define CMP_R_NULL_ARGUMENT 103
# define CMP_R_PKIBODY_ERROR 146
# define CMP_R_PKISTATUSINFO_NOT_FOUND 132
# define CMP_R_POLLING_FAILED 172
# define CMP_R_POTENTIALLY_INVALID_CERTIFICATE 147
# define CMP_R_RECEIVED_ERROR 180
# define CMP_R_RECIPNONCE_UNMATCHED 148
# define CMP_R_REQUEST_NOT_ACCEPTED 149
# define CMP_R_REQUEST_REJECTED_BY_SERVER 182
# define CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED 150
# define CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG 151
# define CMP_R_TOTAL_TIMEOUT 184
# define CMP_R_TRANSACTIONID_UNMATCHED 152
# define CMP_R_TRANSFER_ERROR 159
# define CMP_R_UNEXPECTED_PKIBODY 133
# define CMP_R_UNEXPECTED_PKISTATUS 185
# define CMP_R_UNEXPECTED_PVNO 153
# define CMP_R_UNKNOWN_ALGORITHM_ID 134
# define CMP_R_UNKNOWN_CERT_TYPE 135
# define CMP_R_UNKNOWN_PKISTATUS 186
# define CMP_R_UNSUPPORTED_ALGORITHM 136
# define CMP_R_UNSUPPORTED_KEY_TYPE 137
# define CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC 154
# define CMP_R_VALUE_TOO_LARGE 175
# define CMP_R_VALUE_TOO_SMALL 177
# define CMP_R_WRONG_ALGORITHM_OID 138
# define CMP_R_WRONG_CERTID 189
# define CMP_R_WRONG_CERTID_IN_RP 187
# define CMP_R_WRONG_PBM_VALUE 155
# define CMP_R_WRONG_RP_COMPONENT_COUNT 188
# define CMP_R_WRONG_SERIAL_IN_RP 173
# endif
#endif
diff --git a/include/openssl/dsaerr.h b/include/openssl/dsaerr.h
index 5f0ca8d12a30..26ada57d80ab 100644
--- a/include/openssl/dsaerr.h
+++ b/include/openssl/dsaerr.h
@@ -1,43 +1,44 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
#ifndef OPENSSL_DSAERR_H
# define OPENSSL_DSAERR_H
# pragma once
# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
# include <openssl/cryptoerr_legacy.h>
# ifndef OPENSSL_NO_DSA
/*
* DSA reason codes.
*/
# define DSA_R_BAD_FFC_PARAMETERS 114
# define DSA_R_BAD_Q_VALUE 102
# define DSA_R_BN_DECODE_ERROR 108
# define DSA_R_BN_ERROR 109
# define DSA_R_DECODE_ERROR 104
# define DSA_R_INVALID_DIGEST_TYPE 106
# define DSA_R_INVALID_PARAMETERS 112
# define DSA_R_MISSING_PARAMETERS 101
# define DSA_R_MISSING_PRIVATE_KEY 111
# define DSA_R_MODULUS_TOO_LARGE 103
# define DSA_R_NO_PARAMETERS_SET 107
# define DSA_R_PARAMETER_ENCODING_ERROR 105
# define DSA_R_P_NOT_PRIME 115
# define DSA_R_Q_NOT_PRIME 113
# define DSA_R_SEED_LEN_SMALL 110
+# define DSA_R_TOO_MANY_RETRIES 116
# endif
#endif
diff --git a/include/openssl/ecerr.h b/include/openssl/ecerr.h
index 46405ac62d91..f15f91f6bf05 100644
--- a/include/openssl/ecerr.h
+++ b/include/openssl/ecerr.h
@@ -1,103 +1,104 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
#ifndef OPENSSL_ECERR_H
# define OPENSSL_ECERR_H
# pragma once
# include <openssl/opensslconf.h>
# include <openssl/symhacks.h>
# include <openssl/cryptoerr_legacy.h>
# ifndef OPENSSL_NO_EC
/*
* EC reason codes.
*/
# define EC_R_ASN1_ERROR 115
# define EC_R_BAD_SIGNATURE 156
# define EC_R_BIGNUM_OUT_OF_RANGE 144
# define EC_R_BUFFER_TOO_SMALL 100
# define EC_R_CANNOT_INVERT 165
# define EC_R_COORDINATES_OUT_OF_RANGE 146
# define EC_R_CURVE_DOES_NOT_SUPPORT_ECDH 160
# define EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA 170
# define EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING 159
# define EC_R_DECODE_ERROR 142
# define EC_R_DISCRIMINANT_IS_ZERO 118
# define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119
# define EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED 127
# define EC_R_FAILED_MAKING_PUBLIC_KEY 166
# define EC_R_FIELD_TOO_LARGE 143
# define EC_R_GF2M_NOT_SUPPORTED 147
# define EC_R_GROUP2PKPARAMETERS_FAILURE 120
# define EC_R_I2D_ECPKPARAMETERS_FAILURE 121
# define EC_R_INCOMPATIBLE_OBJECTS 101
# define EC_R_INVALID_A 168
# define EC_R_INVALID_ARGUMENT 112
# define EC_R_INVALID_B 169
# define EC_R_INVALID_COFACTOR 171
# define EC_R_INVALID_COMPRESSED_POINT 110
# define EC_R_INVALID_COMPRESSION_BIT 109
# define EC_R_INVALID_CURVE 141
# define EC_R_INVALID_DIGEST 151
# define EC_R_INVALID_DIGEST_TYPE 138
# define EC_R_INVALID_ENCODING 102
# define EC_R_INVALID_FIELD 103
# define EC_R_INVALID_FORM 104
# define EC_R_INVALID_GENERATOR 173
# define EC_R_INVALID_GROUP_ORDER 122
# define EC_R_INVALID_KEY 116
# define EC_R_INVALID_LENGTH 117
# define EC_R_INVALID_NAMED_GROUP_CONVERSION 174
# define EC_R_INVALID_OUTPUT_LENGTH 161
# define EC_R_INVALID_P 172
# define EC_R_INVALID_PEER_KEY 133
# define EC_R_INVALID_PENTANOMIAL_BASIS 132
# define EC_R_INVALID_PRIVATE_KEY 123
# define EC_R_INVALID_SEED 175
# define EC_R_INVALID_TRINOMIAL_BASIS 137
# define EC_R_KDF_PARAMETER_ERROR 148
# define EC_R_KEYS_NOT_SET 140
# define EC_R_LADDER_POST_FAILURE 136
# define EC_R_LADDER_PRE_FAILURE 153
# define EC_R_LADDER_STEP_FAILURE 162
# define EC_R_MISSING_OID 167
# define EC_R_MISSING_PARAMETERS 124
# define EC_R_MISSING_PRIVATE_KEY 125
# define EC_R_NEED_NEW_SETUP_VALUES 157
# define EC_R_NOT_A_NIST_PRIME 135
# define EC_R_NOT_IMPLEMENTED 126
# define EC_R_NOT_INITIALIZED 111
# define EC_R_NO_PARAMETERS_SET 139
# define EC_R_NO_PRIVATE_VALUE 154
# define EC_R_OPERATION_NOT_SUPPORTED 152
# define EC_R_PASSED_NULL_PARAMETER 134
# define EC_R_PEER_KEY_ERROR 149
# define EC_R_POINT_ARITHMETIC_FAILURE 155
# define EC_R_POINT_AT_INFINITY 106
# define EC_R_POINT_COORDINATES_BLIND_FAILURE 163
# define EC_R_POINT_IS_NOT_ON_CURVE 107
# define EC_R_RANDOM_NUMBER_GENERATION_FAILED 158
# define EC_R_SHARED_INFO_ERROR 150
# define EC_R_SLOT_FULL 108
+# define EC_R_TOO_MANY_RETRIES 176
# define EC_R_UNDEFINED_GENERATOR 113
# define EC_R_UNDEFINED_ORDER 128
# define EC_R_UNKNOWN_COFACTOR 164
# define EC_R_UNKNOWN_GROUP 129
# define EC_R_UNKNOWN_ORDER 114
# define EC_R_UNSUPPORTED_FIELD 131
# define EC_R_WRONG_CURVE_PARAMETERS 145
# define EC_R_WRONG_ORDER 130
# endif
#endif
diff --git a/providers/fips-sources.checksums b/providers/fips-sources.checksums
index 10076d9d2e05..dea6ef04e23d 100644
--- a/providers/fips-sources.checksums
+++ b/providers/fips-sources.checksums
@@ -1,583 +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
92be9ff608331a432e95247a8f4fb9e46897d0cb76f2b6db809b61d44287964a crypto/aes/asm/aes-armv4.pl
953897f86e2de9fa27ef411155ab3aed133af94885f1507e76449c142da78656 crypto/aes/asm/aes-c64xplus.pl
00196f01f5218ad731e6a058d406078f7228a9756d9d73f51c0d0c2a68f885af crypto/aes/asm/aes-ia64.S
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
c7c6694480bb5319690f94826139a93f5c460ebea6dba101b520a76cb956ec93 crypto/aes/asm/aesni-x86_64.pl
f3a8f3c960c0f47aaa8fc2633d18b14e7c7feeccc536b0115a08bc58333122b6 crypto/aes/asm/aesp8-ppc.pl
e397a5781893e97dd90a5a52049633be12a43f379ec5751bca2a6350c39444c8 crypto/aes/asm/aest4-sparcv9.pl
-90d53250761de35280f57463855b1a41403c68dfe22771b2f622c5c9b3418eb4 crypto/aes/asm/aesv8-armx.pl
-15cf92ba0ea6fb216c75bb0c134fa1e1b4159a3f9d3c571b2a8319252c4ae633 crypto/aes/asm/bsaes-armv7.pl
+a097f9d71de7cefa8e93629033ff1986fb01128623ec051d9b5afef55c0e5ebb 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
060bb6620f50af9afecdf97df051b45b9a50be9daf343dfec1cbb29693ce00a4 crypto/aes/asm/vpaes-x86_64.pl
+2bc67270155e2d6c7da87d9070e005ee79cea18311004907edfd6a078003532a crypto/alphacpuid.pl
+0255a480b78bdcc71f76676f496962a9828eb900f53b7be13be96ae3f67fe6db crypto/arm64cpuid.pl
+e0daf54f72dd8fd1bc537d93f34e2a6a887a9ed6027bb33e15a327ef5ff37a42 crypto/armcap.c
+a43f2c1eef16146943745f684f2add7d186924932a47abf7fb0760cba02804e6 crypto/armv4cpuid.pl
16739d54200fb81ca7835b5814f965022a2ab41589c7787e2697e3ea72d4fafa crypto/asn1_dsa.c
819c9fd2b0cae9aab81c3cbd1815c2e22949d75f132f649b5883812d0bbaa39a crypto/bn/asm/alpha-mont.pl
0070595128b250b9ebdebe48ce53d2d27ca16ec4f7c6c8bd169ab2e4a913b2d1 crypto/bn/asm/armv4-gf2m.pl
8c1c53a725b8a4f92b8a353bfeeb393be94198df41c912e3270f9e654417b250 crypto/bn/asm/armv4-mont.pl
8d6192337fedb0012764229d600634f8357c3b74fd38bcbfe8b86ddc6ca96ea2 crypto/bn/asm/armv8-mont.pl
cb4ad7b7461fcb8e2a0d52881158d0211b79544842d4eae36fc566869a2d62c8 crypto/bn/asm/bn-586.pl
636da7e2a66272a81f9c99e90b36c6f132ad6236c739e8b9f2e7315f30b72edd crypto/bn/asm/c64xplus-gf2m.pl
c86664fb974362ee52a454c83c2c4b23fd5b7d64b3c9e23ef1e0dfd130a46ee5 crypto/bn/asm/co-586.pl
199b9b100f194a2a128c14f2a71be5a04d50d069666d90ca5b69baee1318ccb7 crypto/bn/asm/ia64-mont.pl
a511aafbf76647a0c83705d4491c898a5584d300aa449fa6166c8803372946eb crypto/bn/asm/ia64.S
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
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
2f7cbc2c3d93b1bbc4953dda38b9ae0ab3a0a8331a0418d94d9b286183736c9e crypto/bn/asm/sparct4-mont.pl
ca21a9ccbc54e19fb7c2e6cdf286ce7cb08b0fba960c777c6edce5c57ccc2101 crypto/bn/asm/sparcv8.S
fbc93c8dbbecefe66086f58fe9719ed87b13b2cdc61454a10e841228296fecef crypto/bn/asm/sparcv8plus.S
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
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
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
-3962dfaa0142e67115ab84f7809d46d59bd122758be09a081b08b2e0d4743b2e crypto/bn/bn_asm.c
-01a35f971062b97b4953604151d3b6a411be439743b5540aa25b638d2186db6f crypto/bn/bn_blind.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
a29b8b7fa8460f11e50f880e3c3c9e0755b93889bcbb5476206c4d938a9c5735 crypto/bn/bn_exp.c
ec2b6e3af6df473a23e7f1a8522f2554cb0eb5d34e3282458c4a66d242278434 crypto/bn/bn_exp2.c
1abab2cc5466b005b939d156e7d8664a4d42a191c9040dbb83941269d6844f0c crypto/bn/bn_gcd.c
4d6cc7ed36978247a191df1eea0120f8ee97b639ba228793dabe5a8355a1a609 crypto/bn/bn_gf2m.c
081e8a6abc23599307dab3b1a92113a65e0bf8717cbc40c970c7469350bc4581 crypto/bn/bn_intern.c
602ed46fbfe12c899dfb7d9d99ff0dbfff96b454fce3cd02817f3e2488dd9192 crypto/bn/bn_kron.c
-b33295765dc6d3843e3571007e2d6dbe75564645ebf181191a91464706d9fadb crypto/bn/bn_lib.c
-0567e3881c4577f25eb7b93070ac1914251d5ef98e3ac4ebacec09a65a12868c crypto/bn/bn_local.h
+bf73a1788a92142963177fb698bc518af9981bbf0ad9784701fbb2462ca10607 crypto/bn/bn_lib.c
+d5beb9fbac2ff5dc3ccbdfa4d1aabca7225c778cff4e3b05b6d6c63e182637f5 crypto/bn/bn_local.h
07247dc2ccc55f3be525baed92fd20031bbaa80fd0bc56155e80ee0da3fc943d crypto/bn/bn_mod.c
f60f3d49b183b04bcdf9b82f7c961b8c1bcb00e68a2c1166fe9edd95a783356e crypto/bn/bn_mont.c
2da73a76b746a47d8cf8ec8b3e0708c2a34e810abde4b4f1241a49e7f5bb2b60 crypto/bn/bn_mpi.c
76982b18b0803d59b33168b260677e7412970757d3b9513de5c80025290f211d crypto/bn/bn_mul.c
-4e3bf49a788ec36cd1d919475bc410a743931aa144e7c60d603e9c0b448faab4 crypto/bn/bn_nist.c
+1f65ad369352d51af1a75eccf598cb497b400ebd86252f5ca8aac54bbb3cc7bd crypto/bn/bn_nist.c
c6760a724d696b7209f0a71f8483fabcf4f081f7e93e2628284c32ef78f69365 crypto/bn/bn_prime.c
c56ad3073108a0de21c5820a48beae2bccdbf5aa8075ec21738878222eb9adc3 crypto/bn/bn_prime.h
628419eabdb88b265823e43a7a1c88fdfecef79771180836f6089050dc9eadb1 crypto/bn/bn_rand.c
1f6e13da1d9965b341f81bc0842a987a7db9b7de0fa7f7040d49be01b92d282b crypto/bn/bn_recp.c
-626226d4dae8e19530a60d8a94b270b262740550787fc46f686b301a043c705b crypto/bn/bn_rsa_fips186_4.c
+a5c5c9f99961a5a7f22a3dcdce964c8a330f822be17f08652223a20fed747d0a crypto/bn/bn_rsa_fips186_4.c
704b0b4723e5c9e9bae5f3e35f9ae8ae8dca3383929e954de9e5169845abfdb2 crypto/bn/bn_shift.c
622e90766b29e0d25f46474429aebda8eba2246835b9e85dc26da7cdbd49334f crypto/bn/bn_sqr.c
42c8ce944c889abcfcf089d0ad2744b7587696d8d7785efa91b3f7ec53dc062a crypto/bn/bn_sqrt.c
24e62baa56e02f2db6454e10168b7c7fa7638db9221b9acda1803d43f38f36e0 crypto/bn/bn_word.c
-2e69544977adab07422acab5cbb32f4efb7ab68bc160dde711e3f7a8e755b43d crypto/bn/rsa_sup_mul.c
be27115efd36f0077a3ec26b1ff1f586b0b8969ba05d8ffa34b2ff4badf227bf crypto/bn/rsaz_exp.c
c4d64da1cdc732ea918fccd6a7bb2746b03365dd26f7ba1e74e08c307ca4c58e crypto/bn/rsaz_exp.h
5b82cb8dbf3087c2e671871cb0a92e4039223a51af533a2ee996f3bfd47453a7 crypto/bn/rsaz_exp_x2.c
834db8ff36006e5cb53e09ca6c44290124bd23692f4341ea6563b66fcade4cea crypto/bsearch.c
c39334b70e1394e43f378ae8d31b6e6dc125e4d9181e6536d38e649c4eaadb75 crypto/buffer/buffer.c
+5f43844b5d8665de9ab895f93599150a327d73ec2674bbf7d7c512d30163022d crypto/c64xpluscpuid.pl
0e1a41a2d81b5765bca3df448f60bf1fad91e485fe89dd65a7300ffc419e316d crypto/cmac/cmac.c
ff9be205d6d7ff00b0e64508f0eb8d9ec0415fbabc0948d26e308212b3f7b2d8 crypto/context.c
c309d81ea991ddf5be4337afad2fd132169f7443c76f863349d3f3c82f3374e4 crypto/core_algorithm.c
f0fd9eb38bf7f196bbb4d26ce8fdf86d0a4f9db219157e66b2c0ffefb4f42005 crypto/core_fetch.c
02670d631bf0f34cca1e3477079d7fe5de4e03c391cf3992986f44f55319597c 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
d2d0569bea2598bd405f23b60e5283a6ce353f1145a25ff8f28cf15711743156 crypto/dh/dh_check.c
7838e9a35870b0fbcba0aff2f52a2439f64d026e9922bce6e5978c2f22c51120 crypto/dh/dh_gen.c
6b17861887b2535159b9e6ca4f927767dad3e71b6e8be50055bc784f78e92d64 crypto/dh/dh_group_params.c
a5cf5cb464b40f1bc5457dc2a6f2c5ec0f050196603cd2ba7037a23ab64adbf7 crypto/dh/dh_kdf.c
0afa7dd237f9b21b0cfb0de10505facd57eb07ded905d888d43a1de2356d4002 crypto/dh/dh_key.c
b0046b2c4e1d74ff4e93f2486a00f63728909b8a75cbdd29b9100e607f97995c crypto/dh/dh_lib.c
8300775d88db0a1aa26a77eb49d6c4f7252e7fee69e1440de4c40edadc9da044 crypto/dh/dh_local.h
bbcf4fc3067ac462a27d7277973180b7dc140df9262a686c7fbe4318ca01f7b8 crypto/dsa/dsa_backend.c
b9c5992089203123c3fae46e39bb4d05e19854087bca7a30ad1f82a3505deec7 crypto/dsa/dsa_check.c
ae727bf6319eb57e682de35d75ea357921987953b3688365c710e7fba51c7c58 crypto/dsa/dsa_gen.c
b1de1624e590dbf76f76953802ff162cc8de7c5e2eaba897313c866424d6902b crypto/dsa/dsa_key.c
9e436a2e0867920c3a5ac58bc14300cad4ab2c4c8fe5e40b355dfd21bfdfe146 crypto/dsa/dsa_lib.c
f4d52d3897219786c6046bf76abb2f174655c584caa50272bf5d281720df5022 crypto/dsa/dsa_local.h
-f88db9fd73a78e66967e56df442b55230f405b4cd804f31f8696324f0b702f15 crypto/dsa/dsa_ossl.c
-6222aa8f60d7451d974dd87c66995033919f36d7f858cbe609cf731ad1eee34e crypto/dsa/dsa_sign.c
+38062c6eebdb2f88fa0c6592837a96a49de2ae520d3ad483a3e02921c8adb094 crypto/dsa/dsa_ossl.c
+d612fd05ff98816ba6cf37f84c0e31443ad9d840ed587a7ab2066027da390325 crypto/dsa/dsa_sign.c
53fa10cc87ac63e35df661882852dc46ae68e6fee83b842f1aeefe00b8900ee1 crypto/dsa/dsa_vrf.c
-0a206e4c4de4702808cba7c9304bedb66abcbc33e513bc25574a795cd5fa3db0 crypto/ec/asm/ecp_nistp521-ppc64.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
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
1689097ae10e4982a8cbe50c2f6eddb03c83436f331f0b67edb98d6b58adc962 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
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
a8a4690e42b4af60aad822aa8b16196df337906af53ea4db926707f7b596ff27 crypto/ec/ec_local.h
fa901b996eb0e460359cd470843bdb03af7a77a2f1136c5e1d30daef70f3e4d2 crypto/ec/ec_mult.c
129c6b42417bfcf582f4a959cfd65433e6f85b158274f4fa38f9c62615ac9166 crypto/ec/ec_oct.c
c7fba2f2c33f67dafa23caef8c3abd12f5336274a9a07d412b83be0366969ee6 crypto/ec/ecdh_kdf.c
b2cf8f052a5716137da7b0e857ed7a5df5fb513b6d14534199a05e32f2b5a866 crypto/ec/ecdh_ossl.c
-c3750d77c287500884a1ab01def8a6a8500c345d5de1c0f6a70e614fff1b9755 crypto/ec/ecdsa_ossl.c
+099f7836a31643c58bda3829090ea81fe3d5acaa4c6f7b145d8355a4293d0ccc 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
2096e13aa2fbcb0d4b10faca3e3f5359cf66098b0397a6d74c6fca14f5dee659 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
-59d514629005748901718e82f2646ecb1d7fbedbc872726749ce9a5af0d205f2 crypto/evp/digest.c
+1af3872164b4a4757bc7896a24b4d2f8eb2cfb4cba0d872a93db69975693e0a6 crypto/evp/digest.c
838277f228cd3025cf95a9cd435e5606ad1fb5d207bbb057aa29892e6a657c55 crypto/evp/ec_support.c
1c3d1b1f800b1f1f5adb1fdbdd67cdf37ca7ea93b264d1468c72a63c140873ce crypto/evp/evp_enc.c
7f10367f9b6191c4a8c01784130d26b2d778485a41cdac5fa17c9a1c4096f132 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
5016dd7ef8b4cf7e9ea8465c18d1daa4c8808cb589261cf236058ee75bc868d7 crypto/evp/keymgmt_lib.c
-a976cf4e7bfb61e06a147360b748238010d23efb069d191fd023abc38d9a2af9 crypto/evp/keymgmt_meth.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
-b3eebfe75d050bef62a2ce6c13399a2b72bdf60bb540666d01a47691f68931b3 crypto/evp/p_lib.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
4b2dbddf0f9ceed34c3822347138be754fb194febca1c21c46bcc3a5cce33674 crypto/evp/signature.c
b06cb8fd4bd95aae1f66e1e145269c82169257f1a60ef0f78f80a3d4c5131fac crypto/ex_data.c
-709d40d5096497349b8b9e2917e949a0a75e6065df62798d1816866ca7e7b4ca crypto/ffc/ffc_backend.c
+1c8389c5d49616d491978f0f2b2a54ba82d805ec41c8f75c67853216953cf46a crypto/ffc/ffc_backend.c
a12af33e605315cdddd6d759e70cd9632f0f33682b9aa7103ed1ecd354fc7e55 crypto/ffc/ffc_dh.c
854378f57707e31ad02cca6eec94369f91f327288d3665713e249c12f7b13211 crypto/ffc/ffc_key_generate.c
2695c9c8ad9193a8c1ab53d5d09712d50d12c91eb8d62e8a15cbc78f327afe84 crypto/ffc/ffc_key_validate.c
-b18d5d7cfc95163defea41f5a081e90f6a7163a6b81c6cfadb8b470ef2e83fc5 crypto/ffc/ffc_params.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
5482c47c266523129980302426d25839fda662f1544f4b684707e6b272a952c9 crypto/lhash/lhash.c
5d49ce00fc06df1b64cbc139ef45c71e0faf08a33f966bc608c82d574521a49e crypto/lhash/lhash_local.h
f866aafae928db1b439ac950dc90744a2397dfe222672fe68b3798396190c8b0 crypto/mem_clr.c
-183bdca6f855182d7d2c78a5c961b34283f85ea69ac828b700605ee82546397d crypto/modes/asm/aes-gcm-armv8_64.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
72744131007d2389c09665a59a862f5f6bb61b64bd3456e9b400985cb56586b8 crypto/modes/asm/ghash-x86_64.pl
a4e9f2e496bd9362b17a1b5989aa4682647cefcff6117f0607122a9e11a9dfd9 crypto/modes/asm/ghashp8-ppc.pl
0029b5beb1d4cd4c5ad47164c23f3e7c9d1eaff66ef54af025ee26795b11a1c7 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
8aa2504f84a0637b5122f0c963c9d82773ba248bad972ab92be7169995d162b5 crypto/o_str.c
8ddbbdf43131c10dcd4428aef0eff2b1e98b0410accada0fad41a4925868beef crypto/packet.c
a20bfd927d69737c86ca95d3cf636afa8cefd8fe23412d1a3897644a0da21211 crypto/param_build.c
c2fe815fb3fd5efe9a6544cae55f9469063a0f6fb728361737b927f6182ae0bb crypto/param_build_set.c
06e67fdd2a308bf355c8dae2e0acd9af94f6e53d428a7d31966311eb5c0aebc1 crypto/params.c
4fda13f6af05d80b0ab89ec4f5813c274a21a9b4565be958a02d006236cef05c crypto/params_dup.c
a0097ff2da8955fe15ba204cb54f3fd48a06f846e2b9826f507b26acf65715c3 crypto/params_from_text.c
+97cb7414dc2f165d5849ee3b46cdfff0afb067729435d9c01a747e0ca41e230c crypto/ppccap.c
+3ca43596a7528dec8ff9d1a3cd0d68b62640f84b1d6a8b5e4842cfd0be1133ad crypto/ppccpuid.pl
b4d34272a0bd1fbe6562022bf7ea6259b6a5a021a48222d415be47ef5ef2a905 crypto/property/defn_cache.c
7da6ae864beb1a4daa4be31eb41d48141a3a7eb7a263a4937a6889e05656a595 crypto/property/property.c
66da4f28d408133fb544b14aeb9ad4913e7c5c67e2826e53f0dc5bf4d8fada26 crypto/property/property_local.h
921305e62749aec22da4843738bee3448b61e7e30d5309beddc7141ad07a8004 crypto/property/property_parse.c
a7cefda6a117550e2c76e0f307565ce1e11640b11ba10c80e469a837fd1212a3 crypto/property/property_query.c
065698c8d88a5facc0cbc02a3bd0c642c94687a8c5dd79901c942138b406067d crypto/property/property_string.c
9653ec9c1476350a94b9cc7f8be3d99961fd803870c9ac03315298d2909a6a8e 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
9e7dd6fc91d3266d4aa4f0f41b7986381122b7d98114e63ebf04c5ee298b5fda crypto/rsa/rsa_backend.c
38a102cd1da1f6ca5a46e6a22f018237964336274385f5c70cbedcaa6997647e crypto/rsa/rsa_chk.c
e32cfa04221a2a3ea33f7bcb93ee51b84cbeba97e94c1fbf6e420b24f97fc9ce crypto/rsa/rsa_crpt.c
e995da1c2e5007bd7f5907f369fe45ed15f4e657143a85078c755bd5e6863d0b crypto/rsa/rsa_gen.c
74ed75d1d8e0844800504a137bfd81c3dbcb6c4bd58b5d5fe9d0a362092b6e88 crypto/rsa/rsa_lib.c
a65e85be5269d8cb88e86b3413c978fa8994419a671092cbf104ff1a08fda23b crypto/rsa/rsa_local.h
cf0b75cd54b61b9b9a290ef18d0ddce9fb26a029a54eb3f720d9b25188440f00 crypto/rsa/rsa_mp_names.c
5c60f6e05db82e13178d805deb1947b8eee4a905e6e77523d3b288da70a46bb5 crypto/rsa/rsa_none.c
33de2accc3af530fd0a4758eb83d5e1d994bf49bac4512b01387dbae656e1a7d crypto/rsa/rsa_oaep.c
-178c98421b54ec50ee55470a7b1acb771ed22efef2c2c0e059544baa7e6d387e crypto/rsa/rsa_ossl.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
740c022caff3b2487c5838b581cdddcc7de2ceabb504aad72dc0dd70a67bf7cf crypto/rsa/rsa_sp800_56b_check.c
-20e54cf2a8fd23ced0962c5f358cedd8ec0c398a87d33b34f1a4326d11e4892e crypto/rsa/rsa_sp800_56b_gen.c
+3aba73dacebb046faf8d09dc279149b52c629004b524ec33e6d81c8ad0bc31a8 crypto/rsa/rsa_sp800_56b_gen.c
1c1c2aeeb18bf1d69e8f134315b7e50d8f43d30eb1aa5bf42983eec9136a2fdc crypto/rsa/rsa_x931.c
+0acbebed48f6242d595c21e3c1ad69da0daa960d62062e8970209deda144f337 crypto/s390xcap.c
+22205848cfb55116ebf999dced8331b575886a609ce29e6886e6267b2310c337 crypto/s390xcpuid.pl
5fa59240ca885cbc0c1cd026934b226d44fc9c3fdf0c2e7e3a7bd7f4963ca2e5 crypto/self_test_core.c
05c533fde7fdba0c76103e97d881b7224c8427451b453e2f6413552996063e31 crypto/sha/asm/keccak1600-armv4.pl
ca3b2b654f9a8c4bc2fa2538c1f19d17acd4a6b9e0df6a4b81df04efa697e67e crypto/sha/asm/keccak1600-armv8.pl
ef575a7fb4956cc3be4ef10a6aeaa10702eadfc92c86167880690320ce942b26 crypto/sha/asm/keccak1600-avx2.pl
f1dcf75789dfb0c5d7cd35988cb8046f60097bbaf1fbdab32a9269fa5492214c crypto/sha/asm/keccak1600-avx512.pl
63e547b100562d1142512d5b54e16efc276ecb6c743c27873dbcdd7cb917c828 crypto/sha/asm/keccak1600-avx512vl.pl
33bdcc6f7668460c3bdf779633e43bfad62b937042a73acb007b462fc5b0a034 crypto/sha/asm/keccak1600-c64x.pl
09fc831dd39bd90a701e9b16d9e9987cc215252a22e1e0355f5da6c495fca35a crypto/sha/asm/keccak1600-mmx.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
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
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
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
2637a8727dee790812b000f2e02b336f7907949df633dda72938bbaafdb204fe crypto/threads_pthread.c
-7959c65c27280cdb1166a30a27c931befd6cfa4ed109094c40eb5a6d253c790c crypto/threads_win.c
+88423960f0414f6fd41fba4f4c67f9f7260c2741e4788adcd52493e895ec8027 crypto/threads_win.c
fd6c27cf7c6b5449b17f2b725f4203c4c10207f1973db09fd41571efe5de08fd crypto/x86_64cpuid.pl
+bbec287bb9bf35379885f8f8998b7fd9e8fc22efee9e1b299109af0f33a7ee16 crypto/x86cpuid.pl
0a9c484f640d96e918921f57f592e82e99ccdbe35d3138d64b10c7af839e9a07 e_os.h
6f353dc7c8c4d8f24f7ffbf920668ccb224ebb5810805a7c80d96770cd858005 include/crypto/aes_platform.h
8c6f308c1ca774e6127e325c3b80511dbcdc99631f032694d8db53a5c02364ee include/crypto/asn1_dsa.h
-f49a26fc4348f3b79507dc4a04fade82cf870f7c22e6c977f402c859fdd1b98b include/crypto/bn.h
+8ce1b35c6924555ef316c7c51d6c27656869e6da7f513f45b7a7051579e3e54d 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
92aacb3e49288f91b44f97e41933e88fe455706e1dd21a365683c2ab545db131 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
094b69aeb8f349cafa8865b577e253132088c25eabb61b910fab141e6f7d2929 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
-5af9a40c44def13576fe2c0eb082fb73c3565c5e00f902d51b1ed1593d481ccb include/internal/refcount.h
+80d7d12b8b3d9945bde3991cb0d1413d120a58a04b17ac673549789e3f37b18a 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
2cd8163cdc6c93386bc05e8ed983e5ca604d0bf9da65500cab736cfa8bc2b048 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
f20c3c845129a129f5e0b1dae970d86a5c96ab49f2e3f6f364734521e9e1abe3 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
3a57eceec58ab781d79cb0458c2251a233f45ba0ef8f414d148c55ac2dff1bc8 include/openssl/dh.h
836130f5a32bbdce51b97b34758ed1b03a9d06065c187418eaf323dca6adfc6d include/openssl/dherr.h
92ae2c907fd56859e3ae28a085071611be5c9245879305cdf8bad027219e64b6 include/openssl/dsa.h
-335eb40a33cd1e95e7783bda2d031ec2bcf02cff8aa804ba3484d1354452b7ea include/openssl/dsaerr.h
+276d1f6e111ba933bc708e6a0670047cbe0d0b67aabe31807abbbc231de4d8cf include/openssl/dsaerr.h
41bf49e64e1c341a8c17778147ddeba35e88dfd7ff131db6210e801ef25a8fd5 include/openssl/e_os2.h
bc9ec2be442a4f49980ba2c63c8f0da701de1f6e23d7db35d781658f833dd7b9 include/openssl/ebcdic.h
33b6321d1c6b7b1621198346946401bb81472054aa236b03c6f22f247248d2ad include/openssl/ec.h
-dad1943d309aaadb800be4a3056096abec611d81982b83c601b482405e11d5c0 include/openssl/ecerr.h
+7aa8c5bee779af59d4733f6a50f7f6be39f1eb43409e5b3357440f9a7d0ca115 include/openssl/ecerr.h
61c76ee3f12ed0e42503a56421ca00f1cb9a0f4caa5f9c4421c374bcd45917d7 include/openssl/encoder.h
69dd983f45b8ccd551f084796519446552963a18c52b70470d978b597c81b2dc include/openssl/encodererr.h
c6ee8f17d7252bdd0807a124dc6d50a95c32c04e17688b7c2e061998570b7028 include/openssl/err.h.in
12ec111c0e22581e0169be5e1838353a085fb51e3042ef59a7db1cee7da73c5b 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
ba345b0d71f74c9e3d752579e16d11cc70b4b00faa329cc674bc43dd2620e044 providers/common/securitycheck.c
527eda471e26763a5fcf123b2d290234d5c836de7b8ef6eef2166ef439919d82 providers/common/securitycheck_fips.c
abd5997bc33b681a4ab275978b92aebca0806a4a3f0c2f41dacf11b3b6f4e101 providers/fips/fips_entry.c
0f761a26c8fa6ad8d5a15c817afe1741352b21769b2164a2eb7dd50e1f6fe04f providers/fips/fipsprov.c
52b48aece6aa3592593c94b53326410c75efb95ac480697ce414679446b49943 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
-6b082c1af446ef9a2bfe68a9ee4362dfa4f1f09f975f11f9ba2e5010493039c6 providers/implementations/asymciphers/rsa_enc.c
+cd784a44a01a8a30a6be63381344a7f5432e74d40b02ea471c5b0dc943a7ac9d providers/implementations/asymciphers/rsa_enc.c
4db1826ecce8b60cb641bcd7a61430ec8cef73d2fe3cbc06aa33526afe1c954a providers/implementations/ciphers/cipher_aes.c
f9d4b30e7110c90064b990c07430bb79061f4436b06ccaa981b25c306cfbfaa2 providers/implementations/ciphers/cipher_aes.h
89378cce6d31e8c2f221f9f29d0b17622624eb83e4ecec8465f7641f68352917 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
6d6bf36329af3b77f457898294be05fea3940a61cdaf0ed60cfb8d091a94186e 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
710ee60704dd9dffa2a11e2e96596af1f7f84f915cedcedeec7292e0d978317a 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
0264d1ea3ece6f730b342586fb1fe00e3f0ff01e47d53f552864df986bf35573 providers/implementations/ciphers/cipher_aes_ocb.c
88138a1aff9705e608c0557653be92eb4de65b152555a2b79ec8b2a8fae73e8f providers/implementations/ciphers/cipher_aes_ocb.h
855869ab5a8d7a61a11674cfe5d503dfa67f59e7e393730835d1d8cf0ab85c70 providers/implementations/ciphers/cipher_aes_ocb_hw.c
a872195161ac6c3a2cb59c3d15b212e34bb7596a41712258f5d0b5e771e25239 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
-9e07260067083c76d26eb0dd8a8bb4a8dac678812644ff88951a0661be70d9fd providers/implementations/ciphers/cipher_tdes_common.c
+6fc41326c5f464f27b7d31c16d5ad7116d6244b99e242893f6c96d0c61f3639a providers/implementations/ciphers/cipher_tdes_common.c
50645122f08ef4891cd96cace833bd550be7f5278ab785515fd61fe8993c8c25 providers/implementations/ciphers/cipher_tdes_hw.c
6bb3c24bfd872e3b4c779b29e9f962348f6ae3effeb4f243c8ea66abefe8a4fa providers/implementations/ciphers/ciphercommon.c
dd72ea861edf70b94197821ceb00e07165d550934a2e851d62afa5034b79f468 providers/implementations/ciphers/ciphercommon_block.c
4b4106f85e36eb2c07acc5a3ca5ccd77b736b3ac46cc4af786cf57405ecd54b2 providers/implementations/ciphers/ciphercommon_ccm.c
8b6828f188c2590c7d9c6cac13fa0eb6d38a522b0f2859e7c8a766580fa9b66e providers/implementations/ciphers/ciphercommon_ccm_hw.c
3b83f58d6ff1ae77de1ae8bee8a44ea2e5e4491c802b156fa77783ddebd44598 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
0cc02005660c5c340660123decac838c59b7460ef1003d9d50edc604cfd8e375 providers/implementations/exchange/kdf_exch.c
31d3dba3d2e6b043b0d14a74caf6bf1a6c550471fb992a495ab7d3337081a526 providers/implementations/include/prov/ciphercommon.h
6dc876a1a785420e84210f085be6e4c7aca407ffb5433dbca4cd3f1c11bb7f06 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
-04f22d6afbad5a6e806cf3af9a25843ccfefb748e24d97a09830a1677706acd5 providers/implementations/kdfs/hkdf.c
+4e71ffd329f1715d14b54e14036b4b2618deb2fd81675287ce5eeb6c76a31d54 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
37120f8a420de0e44b7dc1f31b50d59520e5318cf546e83684e0c3de5c7b76c5 providers/implementations/keymgmt/dh_kmgmt.c
2a4493c9e68f41d37d7ec69c272005c6df7b1a34db2d49663f52e836e4fd888c providers/implementations/keymgmt/dsa_kmgmt.c
-ed6825fb92d0ab30f9f858ee29dfa403caa22430cccf493f850f993fd03a975e providers/implementations/keymgmt/ec_kmgmt.c
+9bc88451d3ae110c7a108ee73d3b3b6bda801ec3494d2dfb9c9970b85c2d34fe providers/implementations/keymgmt/ec_kmgmt.c
258ae17bb2dd87ed1511a8eb3fe99eed9b77f5c2f757215ff6b3d0e8791fc251 providers/implementations/keymgmt/ec_kmgmt_imexport.inc
d77ece2494e6b12a6201a2806ee5fb24a6dc2fa3e1891a46012a870e0b781ab1 providers/implementations/keymgmt/ecx_kmgmt.c
053a2be39a87f50b877ebdbbf799cf5faf8b2de33b04311d819d212ee1ea329b providers/implementations/keymgmt/kdf_legacy_kmgmt.c
e30357311e4a3e1c78266af6315fd1fc99584bfb09f4a7cd0ddc7261cf1e17e1 providers/implementations/keymgmt/mac_legacy_kmgmt.c
-96b47ba54dcbc05f7ee98c7f78df04e9671b6dbddbc85e3ea53e74ad04663e7a providers/implementations/keymgmt/rsa_kmgmt.c
+19f22fc70a6321441e56d5bd4aab3d01d52d17069d4e4b5cefce0f411ecece75 providers/implementations/keymgmt/rsa_kmgmt.c
aeb42590728ca87b916b8a3d337351b1c82ee0747213e5ce740c2350b3db7185 providers/implementations/macs/cmac_prov.c
e69aa06f8f3c6f5a26702b9f44a844b8589b99dc0ee590953a29e8b9ef10acbe providers/implementations/macs/gmac_prov.c
895c8dc7235b9ad5ff893be0293cbc245a5455e8850195ac7d446646e4ea71d0 providers/implementations/macs/hmac_prov.c
f75fbfe5348f93ad610da7d310f4e8fecf18c0549f27605da25d393c33e0edc2 providers/implementations/macs/kmac_prov.c
bf30274dd6b528ae913984775bd8f29c6c48c0ef06d464d0f738217727b7aa5c providers/implementations/rands/crngt.c
-c7236e6e2e8adce14f8206da0ceef63c7974d4ba1a7dd71b94fa100cac6b46ba providers/implementations/rands/drbg.c
+9d23df7f99beec7392c9d4ed813407050bc2d150098888fe802e2c9705fc33fa providers/implementations/rands/drbg.c
bb5f8161a80d0d1a7ee919af2b167972b00afd62e326252ca6aa93101f315f19 providers/implementations/rands/drbg_ctr.c
a05adc3f6d9d6f948e5ead75f0522ed3164cb5b2d301169242f3cb97c4a7fac3 providers/implementations/rands/drbg_hash.c
0876dfae991028c569631938946e458e6829cacf4cfb673d2b144ae50a3160bb providers/implementations/rands/drbg_hmac.c
fc43558964bdf12442d3f6ab6cc3e6849f7adb42f4d0123a1279819befcf71cb 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
3bb0f342b4cc1b4594ed0986adc47791c0a7b5c1ae7b1888c1fb5edb268a78d9 providers/implementations/signature/mac_legacy_sig.c
-2334c8bba705032b8c1db5dd28e024a45a73b72cae82a2d815fe855445a49d10 providers/implementations/signature/rsa_sig.c
+5b5e51acce1f6e86581de9ee870e64772f69562362b34079ac65c5d6fffaddef providers/implementations/signature/rsa_sig.c
a14e901b02fe095713624db4080b3aa3ca685d43f9ebec03041f992240973346 ssl/record/tls_pad.c
3f2e01a98d9e3fda6cc5cb4b44dd43f6cae4ec34994e8f734d11b1e643e58636 ssl/s3_cbc.c
diff --git a/providers/fips.checksum b/providers/fips.checksum
index 7f7abb3eaa22..077e225c6d93 100644
--- a/providers/fips.checksum
+++ b/providers/fips.checksum
@@ -1 +1 @@
-fd6bce79efec94a99e40c919e0a5ee392514b81cac01d4d46b5c76f27fb1b839 providers/fips-sources.checksums
+d4b8aaf04173ffd7bdd7d64e823002a988146d85c193a4bb8217dc8225583169 providers/fips-sources.checksums
diff --git a/providers/fips.module.sources b/providers/fips.module.sources
index 8861ceaca311..88e918878fc2 100644
--- a/providers/fips.module.sources
+++ b/providers/fips.module.sources
@@ -1,583 +1,595 @@
crypto/aes/aes_cbc.c
crypto/aes/aes_core.c
crypto/aes/aes_ecb.c
crypto/aes/aes_local.h
crypto/aes/aes_misc.c
crypto/aes/asm/aes-586.pl
crypto/aes/asm/aes-armv4.pl
crypto/aes/asm/aes-c64xplus.pl
crypto/aes/asm/aes-ia64.S
crypto/aes/asm/aes-mips.pl
crypto/aes/asm/aes-parisc.pl
crypto/aes/asm/aes-ppc.pl
crypto/aes/asm/aes-s390x.pl
crypto/aes/asm/aes-sparcv9.pl
crypto/aes/asm/aes-x86_64.pl
crypto/aes/asm/aesfx-sparcv9.pl
crypto/aes/asm/aesni-mb-x86_64.pl
crypto/aes/asm/aesni-sha1-x86_64.pl
crypto/aes/asm/aesni-sha256-x86_64.pl
crypto/aes/asm/aesni-x86.pl
crypto/aes/asm/aesni-x86_64.pl
crypto/aes/asm/aesp8-ppc.pl
crypto/aes/asm/aest4-sparcv9.pl
crypto/aes/asm/aesv8-armx.pl
crypto/aes/asm/bsaes-armv7.pl
crypto/aes/asm/bsaes-x86_64.pl
crypto/aes/asm/vpaes-armv8.pl
crypto/aes/asm/vpaes-ppc.pl
crypto/aes/asm/vpaes-x86.pl
crypto/aes/asm/vpaes-x86_64.pl
+crypto/alphacpuid.pl
+crypto/arm64cpuid.pl
+crypto/armcap.c
+crypto/armv4cpuid.pl
crypto/asn1_dsa.c
crypto/bn/asm/alpha-mont.pl
crypto/bn/asm/armv4-gf2m.pl
crypto/bn/asm/armv4-mont.pl
crypto/bn/asm/armv8-mont.pl
crypto/bn/asm/bn-586.pl
crypto/bn/asm/c64xplus-gf2m.pl
crypto/bn/asm/co-586.pl
crypto/bn/asm/ia64-mont.pl
crypto/bn/asm/ia64.S
crypto/bn/asm/mips-mont.pl
crypto/bn/asm/mips.pl
crypto/bn/asm/parisc-mont.pl
crypto/bn/asm/ppc-mont.pl
crypto/bn/asm/ppc.pl
crypto/bn/asm/ppc64-mont-fixed.pl
crypto/bn/asm/ppc64-mont.pl
crypto/bn/asm/rsaz-avx2.pl
crypto/bn/asm/rsaz-avx512.pl
crypto/bn/asm/rsaz-x86_64.pl
crypto/bn/asm/s390x-gf2m.pl
crypto/bn/asm/s390x-mont.pl
crypto/bn/asm/s390x.S
crypto/bn/asm/sparct4-mont.pl
crypto/bn/asm/sparcv8.S
crypto/bn/asm/sparcv8plus.S
crypto/bn/asm/sparcv9-gf2m.pl
crypto/bn/asm/sparcv9-mont.pl
crypto/bn/asm/sparcv9a-mont.pl
crypto/bn/asm/via-mont.pl
crypto/bn/asm/vis3-mont.pl
crypto/bn/asm/x86-gf2m.pl
crypto/bn/asm/x86-mont.pl
crypto/bn/asm/x86_64-gcc.c
crypto/bn/asm/x86_64-gf2m.pl
crypto/bn/asm/x86_64-mont.pl
crypto/bn/asm/x86_64-mont5.pl
crypto/bn/bn_add.c
crypto/bn/bn_asm.c
crypto/bn/bn_blind.c
crypto/bn/bn_const.c
crypto/bn/bn_conv.c
crypto/bn/bn_ctx.c
crypto/bn/bn_dh.c
crypto/bn/bn_div.c
crypto/bn/bn_exp.c
crypto/bn/bn_exp2.c
crypto/bn/bn_gcd.c
crypto/bn/bn_gf2m.c
crypto/bn/bn_intern.c
crypto/bn/bn_kron.c
crypto/bn/bn_lib.c
crypto/bn/bn_local.h
crypto/bn/bn_mod.c
crypto/bn/bn_mont.c
crypto/bn/bn_mpi.c
crypto/bn/bn_mul.c
crypto/bn/bn_nist.c
crypto/bn/bn_prime.c
crypto/bn/bn_prime.h
crypto/bn/bn_rand.c
crypto/bn/bn_recp.c
crypto/bn/bn_rsa_fips186_4.c
crypto/bn/bn_shift.c
crypto/bn/bn_sqr.c
crypto/bn/bn_sqrt.c
crypto/bn/bn_word.c
-crypto/bn/rsa_sup_mul.c
crypto/bn/rsaz_exp.c
crypto/bn/rsaz_exp.h
crypto/bn/rsaz_exp_x2.c
crypto/bsearch.c
crypto/buffer/buffer.c
+crypto/c64xpluscpuid.pl
crypto/cmac/cmac.c
crypto/context.c
crypto/core_algorithm.c
crypto/core_fetch.c
crypto/core_namemap.c
crypto/cpuid.c
crypto/cryptlib.c
crypto/ctype.c
crypto/der_writer.c
crypto/des/des_enc.c
crypto/des/des_local.h
crypto/des/ecb3_enc.c
crypto/des/fcrypt_b.c
crypto/des/ncbc_enc.c
crypto/des/set_key.c
crypto/des/spr.h
crypto/dh/dh_backend.c
crypto/dh/dh_check.c
crypto/dh/dh_gen.c
crypto/dh/dh_group_params.c
crypto/dh/dh_kdf.c
crypto/dh/dh_key.c
crypto/dh/dh_lib.c
crypto/dh/dh_local.h
crypto/dsa/dsa_backend.c
crypto/dsa/dsa_check.c
crypto/dsa/dsa_gen.c
crypto/dsa/dsa_key.c
crypto/dsa/dsa_lib.c
crypto/dsa/dsa_local.h
crypto/dsa/dsa_ossl.c
crypto/dsa/dsa_sign.c
crypto/dsa/dsa_vrf.c
crypto/ec/asm/ecp_nistp521-ppc64.pl
crypto/ec/asm/ecp_nistz256-armv4.pl
crypto/ec/asm/ecp_nistz256-armv8.pl
crypto/ec/asm/ecp_nistz256-ppc64.pl
crypto/ec/asm/ecp_nistz256-sparcv9.pl
crypto/ec/asm/ecp_nistz256-x86.pl
crypto/ec/asm/ecp_nistz256-x86_64.pl
crypto/ec/asm/x25519-ppc64.pl
crypto/ec/asm/x25519-x86_64.pl
crypto/ec/curve25519.c
crypto/ec/curve448/arch_32/f_impl32.c
crypto/ec/curve448/arch_64/arch_intrinsics.h
crypto/ec/curve448/arch_64/f_impl.h
crypto/ec/curve448/arch_64/f_impl64.c
crypto/ec/curve448/curve448.c
crypto/ec/curve448/curve448_local.h
crypto/ec/curve448/curve448_tables.c
crypto/ec/curve448/curve448utils.h
crypto/ec/curve448/ed448.h
crypto/ec/curve448/eddsa.c
crypto/ec/curve448/f_generic.c
crypto/ec/curve448/field.h
crypto/ec/curve448/point_448.h
crypto/ec/curve448/scalar.c
crypto/ec/curve448/word.h
crypto/ec/ec2_oct.c
crypto/ec/ec2_smpl.c
crypto/ec/ec_asn1.c
crypto/ec/ec_backend.c
crypto/ec/ec_check.c
crypto/ec/ec_curve.c
crypto/ec/ec_cvt.c
crypto/ec/ec_key.c
crypto/ec/ec_kmeth.c
crypto/ec/ec_lib.c
crypto/ec/ec_local.h
crypto/ec/ec_mult.c
crypto/ec/ec_oct.c
crypto/ec/ecdh_kdf.c
crypto/ec/ecdh_ossl.c
crypto/ec/ecdsa_ossl.c
crypto/ec/ecdsa_sign.c
crypto/ec/ecdsa_vrf.c
crypto/ec/ecp_mont.c
crypto/ec/ecp_nist.c
crypto/ec/ecp_nistz256.c
crypto/ec/ecp_oct.c
crypto/ec/ecp_smpl.c
crypto/ec/ecx_backend.c
crypto/ec/ecx_backend.h
crypto/ec/ecx_key.c
crypto/evp/asymcipher.c
crypto/evp/dh_support.c
crypto/evp/digest.c
crypto/evp/ec_support.c
crypto/evp/evp_enc.c
crypto/evp/evp_fetch.c
crypto/evp/evp_lib.c
crypto/evp/evp_local.h
crypto/evp/evp_rand.c
crypto/evp/evp_utils.c
crypto/evp/exchange.c
crypto/evp/kdf_lib.c
crypto/evp/kdf_meth.c
crypto/evp/kem.c
crypto/evp/keymgmt_lib.c
crypto/evp/keymgmt_meth.c
crypto/evp/m_sigver.c
crypto/evp/mac_lib.c
crypto/evp/mac_meth.c
crypto/evp/p_lib.c
crypto/evp/pmeth_check.c
crypto/evp/pmeth_gn.c
crypto/evp/pmeth_lib.c
crypto/evp/signature.c
crypto/ex_data.c
crypto/ffc/ffc_backend.c
crypto/ffc/ffc_dh.c
crypto/ffc/ffc_key_generate.c
crypto/ffc/ffc_key_validate.c
crypto/ffc/ffc_params.c
crypto/ffc/ffc_params_generate.c
crypto/ffc/ffc_params_validate.c
crypto/hmac/hmac.c
crypto/hmac/hmac_local.h
+crypto/ia64cpuid.S
crypto/initthread.c
crypto/lhash/lhash.c
crypto/lhash/lhash_local.h
crypto/mem_clr.c
crypto/modes/asm/aes-gcm-armv8_64.pl
crypto/modes/asm/aesni-gcm-x86_64.pl
crypto/modes/asm/ghash-alpha.pl
crypto/modes/asm/ghash-armv4.pl
crypto/modes/asm/ghash-c64xplus.pl
crypto/modes/asm/ghash-ia64.pl
crypto/modes/asm/ghash-parisc.pl
crypto/modes/asm/ghash-s390x.pl
crypto/modes/asm/ghash-sparcv9.pl
crypto/modes/asm/ghash-x86.pl
crypto/modes/asm/ghash-x86_64.pl
crypto/modes/asm/ghashp8-ppc.pl
crypto/modes/asm/ghashv8-armx.pl
crypto/modes/cbc128.c
crypto/modes/ccm128.c
crypto/modes/cfb128.c
crypto/modes/ctr128.c
crypto/modes/gcm128.c
crypto/modes/ofb128.c
crypto/modes/wrap128.c
crypto/modes/xts128.c
crypto/o_str.c
crypto/packet.c
crypto/param_build.c
crypto/param_build_set.c
crypto/params.c
crypto/params_dup.c
crypto/params_from_text.c
+crypto/ppccap.c
+crypto/ppccpuid.pl
crypto/property/defn_cache.c
crypto/property/property.c
crypto/property/property_local.h
crypto/property/property_parse.c
crypto/property/property_query.c
crypto/property/property_string.c
crypto/provider_core.c
crypto/provider_local.h
crypto/provider_predefined.c
crypto/rand/rand_lib.c
crypto/rand/rand_local.h
crypto/rsa/rsa_acvp_test_params.c
crypto/rsa/rsa_backend.c
crypto/rsa/rsa_chk.c
crypto/rsa/rsa_crpt.c
crypto/rsa/rsa_gen.c
crypto/rsa/rsa_lib.c
crypto/rsa/rsa_local.h
crypto/rsa/rsa_mp_names.c
crypto/rsa/rsa_none.c
crypto/rsa/rsa_oaep.c
crypto/rsa/rsa_ossl.c
crypto/rsa/rsa_pk1.c
crypto/rsa/rsa_pss.c
crypto/rsa/rsa_schemes.c
crypto/rsa/rsa_sign.c
crypto/rsa/rsa_sp800_56b_check.c
crypto/rsa/rsa_sp800_56b_gen.c
crypto/rsa/rsa_x931.c
+crypto/s390xcap.c
+crypto/s390xcpuid.pl
crypto/self_test_core.c
crypto/sha/asm/keccak1600-armv4.pl
crypto/sha/asm/keccak1600-armv8.pl
crypto/sha/asm/keccak1600-avx2.pl
crypto/sha/asm/keccak1600-avx512.pl
crypto/sha/asm/keccak1600-avx512vl.pl
crypto/sha/asm/keccak1600-c64x.pl
crypto/sha/asm/keccak1600-mmx.pl
crypto/sha/asm/keccak1600-ppc64.pl
crypto/sha/asm/keccak1600-s390x.pl
crypto/sha/asm/keccak1600-x86_64.pl
crypto/sha/asm/keccak1600p8-ppc.pl
crypto/sha/asm/sha1-586.pl
crypto/sha/asm/sha1-alpha.pl
crypto/sha/asm/sha1-armv4-large.pl
crypto/sha/asm/sha1-armv8.pl
crypto/sha/asm/sha1-c64xplus.pl
crypto/sha/asm/sha1-ia64.pl
crypto/sha/asm/sha1-mb-x86_64.pl
crypto/sha/asm/sha1-mips.pl
crypto/sha/asm/sha1-parisc.pl
crypto/sha/asm/sha1-ppc.pl
crypto/sha/asm/sha1-s390x.pl
crypto/sha/asm/sha1-sparcv9.pl
crypto/sha/asm/sha1-sparcv9a.pl
crypto/sha/asm/sha1-thumb.pl
crypto/sha/asm/sha1-x86_64.pl
crypto/sha/asm/sha256-586.pl
crypto/sha/asm/sha256-armv4.pl
crypto/sha/asm/sha256-c64xplus.pl
crypto/sha/asm/sha256-mb-x86_64.pl
crypto/sha/asm/sha512-586.pl
crypto/sha/asm/sha512-armv4.pl
crypto/sha/asm/sha512-armv8.pl
crypto/sha/asm/sha512-c64xplus.pl
crypto/sha/asm/sha512-ia64.pl
crypto/sha/asm/sha512-mips.pl
crypto/sha/asm/sha512-parisc.pl
crypto/sha/asm/sha512-ppc.pl
crypto/sha/asm/sha512-s390x.pl
crypto/sha/asm/sha512-sparcv9.pl
crypto/sha/asm/sha512-x86_64.pl
crypto/sha/asm/sha512p8-ppc.pl
crypto/sha/keccak1600.c
crypto/sha/sha1dgst.c
crypto/sha/sha256.c
crypto/sha/sha3.c
crypto/sha/sha512.c
crypto/sha/sha_local.h
+crypto/sparccpuid.S
+crypto/sparcv9cap.c
crypto/sparse_array.c
crypto/stack/stack.c
crypto/threads_lib.c
crypto/threads_none.c
crypto/threads_pthread.c
crypto/threads_win.c
crypto/x86_64cpuid.pl
+crypto/x86cpuid.pl
e_os.h
include/crypto/aes_platform.h
include/crypto/asn1_dsa.h
include/crypto/bn.h
include/crypto/bn_conf.h.in
include/crypto/bn_dh.h
include/crypto/cryptlib.h
include/crypto/ctype.h
include/crypto/des_platform.h
include/crypto/dh.h
include/crypto/dsa.h
include/crypto/ec.h
include/crypto/ecx.h
include/crypto/evp.h
include/crypto/lhash.h
include/crypto/md32_common.h
include/crypto/modes.h
include/crypto/rand.h
include/crypto/rand_pool.h
include/crypto/rsa.h
include/crypto/security_bits.h
include/crypto/sha.h
include/crypto/sparse_array.h
include/crypto/types.h
include/internal/bio.h
include/internal/constant_time.h
include/internal/core.h
include/internal/cryptlib.h
include/internal/deprecated.h
include/internal/der.h
include/internal/dso.h
include/internal/dsoerr.h
include/internal/endian.h
include/internal/ffc.h
include/internal/namemap.h
include/internal/nelem.h
include/internal/numbers.h
include/internal/packet.h
include/internal/param_build_set.h
include/internal/property.h
include/internal/propertyerr.h
include/internal/provider.h
include/internal/refcount.h
include/internal/sha3.h
include/internal/sizes.h
include/internal/symhacks.h
include/internal/thread_once.h
include/internal/tlsgroups.h
include/internal/tsan_assist.h
include/openssl/aes.h
include/openssl/asn1.h.in
include/openssl/asn1err.h
include/openssl/asn1t.h.in
include/openssl/bio.h.in
include/openssl/bioerr.h
include/openssl/bn.h
include/openssl/bnerr.h
include/openssl/buffer.h
include/openssl/buffererr.h
include/openssl/cmac.h
include/openssl/conf.h.in
include/openssl/conferr.h
include/openssl/configuration.h.in
include/openssl/conftypes.h
include/openssl/core.h
include/openssl/core_dispatch.h
include/openssl/core_names.h
include/openssl/crypto.h.in
include/openssl/cryptoerr.h
include/openssl/cryptoerr_legacy.h
include/openssl/des.h
include/openssl/dh.h
include/openssl/dherr.h
include/openssl/dsa.h
include/openssl/dsaerr.h
include/openssl/e_os2.h
include/openssl/ebcdic.h
include/openssl/ec.h
include/openssl/ecerr.h
include/openssl/encoder.h
include/openssl/encodererr.h
include/openssl/err.h.in
include/openssl/evp.h
include/openssl/evperr.h
include/openssl/fips_names.h
include/openssl/fipskey.h.in
include/openssl/hmac.h
include/openssl/kdf.h
include/openssl/lhash.h.in
include/openssl/macros.h
include/openssl/modes.h
include/openssl/obj_mac.h
include/openssl/objects.h
include/openssl/objectserr.h
include/openssl/opensslconf.h
include/openssl/opensslv.h.in
include/openssl/param_build.h
include/openssl/params.h
include/openssl/prov_ssl.h
include/openssl/proverr.h
include/openssl/provider.h
include/openssl/rand.h
include/openssl/randerr.h
include/openssl/rsa.h
include/openssl/rsaerr.h
include/openssl/safestack.h.in
include/openssl/self_test.h
include/openssl/sha.h
include/openssl/stack.h
include/openssl/symhacks.h
include/openssl/trace.h
include/openssl/types.h
providers/common/bio_prov.c
providers/common/capabilities.c
providers/common/der/der_digests_gen.c.in
providers/common/der/der_dsa_gen.c.in
providers/common/der/der_dsa_key.c
providers/common/der/der_dsa_sig.c
providers/common/der/der_ec_gen.c.in
providers/common/der/der_ec_key.c
providers/common/der/der_ec_sig.c
providers/common/der/der_ecx_gen.c.in
providers/common/der/der_ecx_key.c
providers/common/der/der_rsa_gen.c.in
providers/common/der/der_rsa_key.c
providers/common/der/der_rsa_sig.c
providers/common/der/der_wrap_gen.c.in
providers/common/digest_to_nid.c
providers/common/include/prov/bio.h
providers/common/include/prov/der_digests.h.in
providers/common/include/prov/der_dsa.h.in
providers/common/include/prov/der_ec.h.in
providers/common/include/prov/der_ecx.h.in
providers/common/include/prov/der_rsa.h.in
providers/common/include/prov/der_wrap.h.in
providers/common/include/prov/proverr.h
providers/common/include/prov/provider_ctx.h
providers/common/include/prov/provider_util.h
providers/common/include/prov/providercommon.h
providers/common/include/prov/securitycheck.h
providers/common/provider_ctx.c
providers/common/provider_err.c
providers/common/provider_seeding.c
providers/common/provider_util.c
providers/common/securitycheck.c
providers/common/securitycheck_fips.c
providers/fips/fips_entry.c
providers/fips/fipsprov.c
providers/fips/self_test.c
providers/fips/self_test.h
providers/fips/self_test_data.inc
providers/fips/self_test_kats.c
providers/implementations/asymciphers/rsa_enc.c
providers/implementations/ciphers/cipher_aes.c
providers/implementations/ciphers/cipher_aes.h
providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c
providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.h
providers/implementations/ciphers/cipher_aes_cbc_hmac_sha1_hw.c
providers/implementations/ciphers/cipher_aes_cbc_hmac_sha256_hw.c
providers/implementations/ciphers/cipher_aes_ccm.c
providers/implementations/ciphers/cipher_aes_ccm.h
providers/implementations/ciphers/cipher_aes_ccm_hw.c
providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc
providers/implementations/ciphers/cipher_aes_cts.inc
providers/implementations/ciphers/cipher_aes_gcm.c
providers/implementations/ciphers/cipher_aes_gcm.h
providers/implementations/ciphers/cipher_aes_gcm_hw.c
providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc
providers/implementations/ciphers/cipher_aes_hw.c
providers/implementations/ciphers/cipher_aes_hw_aesni.inc
providers/implementations/ciphers/cipher_aes_ocb.c
providers/implementations/ciphers/cipher_aes_ocb.h
providers/implementations/ciphers/cipher_aes_ocb_hw.c
providers/implementations/ciphers/cipher_aes_wrp.c
providers/implementations/ciphers/cipher_aes_xts.c
providers/implementations/ciphers/cipher_aes_xts.h
providers/implementations/ciphers/cipher_aes_xts_fips.c
providers/implementations/ciphers/cipher_aes_xts_hw.c
providers/implementations/ciphers/cipher_cts.c
providers/implementations/ciphers/cipher_cts.h
providers/implementations/ciphers/cipher_tdes.c
providers/implementations/ciphers/cipher_tdes.h
providers/implementations/ciphers/cipher_tdes_common.c
providers/implementations/ciphers/cipher_tdes_hw.c
providers/implementations/ciphers/ciphercommon.c
providers/implementations/ciphers/ciphercommon_block.c
providers/implementations/ciphers/ciphercommon_ccm.c
providers/implementations/ciphers/ciphercommon_ccm_hw.c
providers/implementations/ciphers/ciphercommon_gcm.c
providers/implementations/ciphers/ciphercommon_gcm_hw.c
providers/implementations/ciphers/ciphercommon_hw.c
providers/implementations/ciphers/ciphercommon_local.h
providers/implementations/digests/digestcommon.c
providers/implementations/digests/sha2_prov.c
providers/implementations/digests/sha3_prov.c
providers/implementations/exchange/dh_exch.c
providers/implementations/exchange/ecdh_exch.c
providers/implementations/exchange/ecx_exch.c
providers/implementations/exchange/kdf_exch.c
providers/implementations/include/prov/ciphercommon.h
providers/implementations/include/prov/ciphercommon_aead.h
providers/implementations/include/prov/ciphercommon_ccm.h
providers/implementations/include/prov/ciphercommon_gcm.h
providers/implementations/include/prov/digestcommon.h
providers/implementations/include/prov/implementations.h
providers/implementations/include/prov/kdfexchange.h
providers/implementations/include/prov/macsignature.h
providers/implementations/include/prov/names.h
providers/implementations/include/prov/seeding.h
providers/implementations/kdfs/hkdf.c
providers/implementations/kdfs/kbkdf.c
providers/implementations/kdfs/pbkdf2.c
providers/implementations/kdfs/pbkdf2.h
providers/implementations/kdfs/pbkdf2_fips.c
providers/implementations/kdfs/sshkdf.c
providers/implementations/kdfs/sskdf.c
providers/implementations/kdfs/tls1_prf.c
providers/implementations/kdfs/x942kdf.c
providers/implementations/kem/rsa_kem.c
providers/implementations/keymgmt/dh_kmgmt.c
providers/implementations/keymgmt/dsa_kmgmt.c
providers/implementations/keymgmt/ec_kmgmt.c
providers/implementations/keymgmt/ec_kmgmt_imexport.inc
providers/implementations/keymgmt/ecx_kmgmt.c
providers/implementations/keymgmt/kdf_legacy_kmgmt.c
providers/implementations/keymgmt/mac_legacy_kmgmt.c
providers/implementations/keymgmt/rsa_kmgmt.c
providers/implementations/macs/cmac_prov.c
providers/implementations/macs/gmac_prov.c
providers/implementations/macs/hmac_prov.c
providers/implementations/macs/kmac_prov.c
providers/implementations/rands/crngt.c
providers/implementations/rands/drbg.c
providers/implementations/rands/drbg_ctr.c
providers/implementations/rands/drbg_hash.c
providers/implementations/rands/drbg_hmac.c
providers/implementations/rands/drbg_local.h
providers/implementations/rands/test_rng.c
providers/implementations/signature/dsa_sig.c
providers/implementations/signature/ecdsa_sig.c
providers/implementations/signature/eddsa_sig.c
providers/implementations/signature/mac_legacy_sig.c
providers/implementations/signature/rsa_sig.c
ssl/record/tls_pad.c
ssl/s3_cbc.c
diff --git a/providers/implementations/asymciphers/rsa_enc.c b/providers/implementations/asymciphers/rsa_enc.c
index 568452ec56a2..d8659680587e 100644
--- a/providers/implementations/asymciphers/rsa_enc.c
+++ b/providers/implementations/asymciphers/rsa_enc.c
@@ -1,588 +1,590 @@
/*
- * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/*
* RSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.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 <openssl/proverr.h>
/* Just for SSL_MAX_MASTER_KEY_LENGTH */
#include <openssl/prov_ssl.h>
#include "internal/constant_time.h"
#include "internal/sizes.h"
#include "crypto/rsa.h"
#include "prov/provider_ctx.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#include "prov/securitycheck.h"
#include <stdlib.h>
static OSSL_FUNC_asym_cipher_newctx_fn rsa_newctx;
static OSSL_FUNC_asym_cipher_encrypt_init_fn rsa_encrypt_init;
static OSSL_FUNC_asym_cipher_encrypt_fn rsa_encrypt;
static OSSL_FUNC_asym_cipher_decrypt_init_fn rsa_decrypt_init;
static OSSL_FUNC_asym_cipher_decrypt_fn rsa_decrypt;
static OSSL_FUNC_asym_cipher_freectx_fn rsa_freectx;
static OSSL_FUNC_asym_cipher_dupctx_fn rsa_dupctx;
static OSSL_FUNC_asym_cipher_get_ctx_params_fn rsa_get_ctx_params;
static OSSL_FUNC_asym_cipher_gettable_ctx_params_fn rsa_gettable_ctx_params;
static OSSL_FUNC_asym_cipher_set_ctx_params_fn rsa_set_ctx_params;
static OSSL_FUNC_asym_cipher_settable_ctx_params_fn rsa_settable_ctx_params;
static OSSL_ITEM padding_item[] = {
{ RSA_PKCS1_PADDING, OSSL_PKEY_RSA_PAD_MODE_PKCSV15 },
{ RSA_NO_PADDING, OSSL_PKEY_RSA_PAD_MODE_NONE },
{ RSA_PKCS1_OAEP_PADDING, OSSL_PKEY_RSA_PAD_MODE_OAEP }, /* Correct spelling first */
{ RSA_PKCS1_OAEP_PADDING, "oeap" },
{ RSA_X931_PADDING, OSSL_PKEY_RSA_PAD_MODE_X931 },
{ 0, NULL }
};
/*
* 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 pad_mode;
int operation;
/* OAEP message digest */
EVP_MD *oaep_md;
/* message digest for MGF1 */
EVP_MD *mgf1_md;
/* OAEP label */
unsigned char *oaep_label;
size_t oaep_labellen;
/* TLS padding */
unsigned int client_version;
unsigned int alt_version;
} PROV_RSA_CTX;
static void *rsa_newctx(void *provctx)
{
PROV_RSA_CTX *prsactx;
if (!ossl_prov_is_running())
return NULL;
prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX));
if (prsactx == NULL)
return NULL;
prsactx->libctx = PROV_LIBCTX_OF(provctx);
return prsactx;
}
static int rsa_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[],
int operation)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
if (!ossl_prov_is_running() || 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;
prsactx->operation = operation;
switch (RSA_test_flags(prsactx->rsa, RSA_FLAG_TYPE_MASK)) {
case RSA_FLAG_TYPE_RSA:
prsactx->pad_mode = RSA_PKCS1_PADDING;
break;
default:
/* This should not happen due to the check above */
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
return 0;
}
return rsa_set_ctx_params(prsactx, params);
}
static int rsa_encrypt_init(void *vprsactx, void *vrsa,
const OSSL_PARAM params[])
{
return rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_ENCRYPT);
}
static int rsa_decrypt_init(void *vprsactx, void *vrsa,
const OSSL_PARAM params[])
{
return rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_DECRYPT);
}
static int rsa_encrypt(void *vprsactx, unsigned char *out, size_t *outlen,
size_t outsize, const unsigned char *in, size_t inlen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
int ret;
if (!ossl_prov_is_running())
return 0;
if (out == NULL) {
size_t len = RSA_size(prsactx->rsa);
if (len == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
return 0;
}
*outlen = len;
return 1;
}
if (prsactx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
int rsasize = RSA_size(prsactx->rsa);
unsigned char *tbuf;
if ((tbuf = OPENSSL_malloc(rsasize)) == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
if (prsactx->oaep_md == NULL) {
- OPENSSL_free(tbuf);
prsactx->oaep_md = EVP_MD_fetch(prsactx->libctx, "SHA-1", NULL);
- ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
- return 0;
+ if (prsactx->oaep_md == NULL) {
+ OPENSSL_free(tbuf);
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
}
ret =
ossl_rsa_padding_add_PKCS1_OAEP_mgf1_ex(prsactx->libctx, tbuf,
rsasize, in, inlen,
prsactx->oaep_label,
prsactx->oaep_labellen,
prsactx->oaep_md,
prsactx->mgf1_md);
if (!ret) {
OPENSSL_free(tbuf);
return 0;
}
ret = RSA_public_encrypt(rsasize, tbuf, out, prsactx->rsa,
RSA_NO_PADDING);
OPENSSL_free(tbuf);
} else {
ret = RSA_public_encrypt(inlen, in, out, prsactx->rsa,
prsactx->pad_mode);
}
/* A ret value of 0 is not an error */
if (ret < 0)
return ret;
*outlen = ret;
return 1;
}
static int rsa_decrypt(void *vprsactx, unsigned char *out, size_t *outlen,
size_t outsize, const unsigned char *in, size_t inlen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
int ret;
size_t len = RSA_size(prsactx->rsa);
if (!ossl_prov_is_running())
return 0;
if (prsactx->pad_mode == RSA_PKCS1_WITH_TLS_PADDING) {
if (out == NULL) {
*outlen = SSL_MAX_MASTER_KEY_LENGTH;
return 1;
}
if (outsize < SSL_MAX_MASTER_KEY_LENGTH) {
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH);
return 0;
}
} else {
if (out == NULL) {
if (len == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
return 0;
}
*outlen = len;
return 1;
}
if (outsize < len) {
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH);
return 0;
}
}
if (prsactx->pad_mode == RSA_PKCS1_OAEP_PADDING
|| prsactx->pad_mode == RSA_PKCS1_WITH_TLS_PADDING) {
unsigned char *tbuf;
if ((tbuf = OPENSSL_malloc(len)) == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
ret = RSA_private_decrypt(inlen, in, tbuf, prsactx->rsa,
RSA_NO_PADDING);
/*
* With no padding then, on success ret should be len, otherwise an
* error occurred (non-constant time)
*/
if (ret != (int)len) {
OPENSSL_free(tbuf);
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_DECRYPT);
return 0;
}
if (prsactx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
if (prsactx->oaep_md == NULL) {
prsactx->oaep_md = EVP_MD_fetch(prsactx->libctx, "SHA-1", NULL);
if (prsactx->oaep_md == NULL) {
OPENSSL_free(tbuf);
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
return 0;
}
}
ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, outsize, tbuf,
len, len,
prsactx->oaep_label,
prsactx->oaep_labellen,
prsactx->oaep_md,
prsactx->mgf1_md);
} else {
/* RSA_PKCS1_WITH_TLS_PADDING */
if (prsactx->client_version <= 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_TLS_CLIENT_VERSION);
OPENSSL_free(tbuf);
return 0;
}
ret = ossl_rsa_padding_check_PKCS1_type_2_TLS(
prsactx->libctx, out, outsize, tbuf, len,
prsactx->client_version, prsactx->alt_version);
}
OPENSSL_free(tbuf);
} else {
ret = RSA_private_decrypt(inlen, in, out, prsactx->rsa,
prsactx->pad_mode);
}
*outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret);
ret = constant_time_select_int(constant_time_msb(ret), 0, 1);
return ret;
}
static void rsa_freectx(void *vprsactx)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
RSA_free(prsactx->rsa);
EVP_MD_free(prsactx->oaep_md);
EVP_MD_free(prsactx->mgf1_md);
OPENSSL_free(prsactx->oaep_label);
OPENSSL_free(prsactx);
}
static void *rsa_dupctx(void *vprsactx)
{
PROV_RSA_CTX *srcctx = (PROV_RSA_CTX *)vprsactx;
PROV_RSA_CTX *dstctx;
if (!ossl_prov_is_running())
return NULL;
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;
}
if (dstctx->oaep_md != NULL && !EVP_MD_up_ref(dstctx->oaep_md)) {
RSA_free(dstctx->rsa);
OPENSSL_free(dstctx);
return NULL;
}
if (dstctx->mgf1_md != NULL && !EVP_MD_up_ref(dstctx->mgf1_md)) {
RSA_free(dstctx->rsa);
EVP_MD_free(dstctx->oaep_md);
OPENSSL_free(dstctx);
return NULL;
}
return dstctx;
}
static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
OSSL_PARAM *p;
if (prsactx == NULL)
return 0;
p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE);
if (p != NULL)
switch (p->data_type) {
case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
if (!OSSL_PARAM_set_int(p, prsactx->pad_mode))
return 0;
break;
case OSSL_PARAM_UTF8_STRING:
{
int i;
const char *word = NULL;
for (i = 0; padding_item[i].id != 0; i++) {
if (prsactx->pad_mode == (int)padding_item[i].id) {
word = padding_item[i].ptr;
break;
}
}
if (word != NULL) {
if (!OSSL_PARAM_set_utf8_string(p, word))
return 0;
} else {
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
}
}
break;
default:
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST);
if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->oaep_md == NULL
? ""
: EVP_MD_get0_name(prsactx->oaep_md)))
return 0;
p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST);
if (p != NULL) {
EVP_MD *mgf1_md = prsactx->mgf1_md == NULL ? prsactx->oaep_md
: prsactx->mgf1_md;
if (!OSSL_PARAM_set_utf8_string(p, mgf1_md == NULL
? ""
: EVP_MD_get0_name(mgf1_md)))
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL);
if (p != NULL &&
!OSSL_PARAM_set_octet_ptr(p, prsactx->oaep_label,
prsactx->oaep_labellen))
return 0;
p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION);
if (p != NULL && !OSSL_PARAM_set_uint(p, prsactx->client_version))
return 0;
p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION);
if (p != NULL && !OSSL_PARAM_set_uint(p, prsactx->alt_version))
return 0;
return 1;
}
static const OSSL_PARAM known_gettable_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, NULL, 0),
OSSL_PARAM_DEFN(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, OSSL_PARAM_OCTET_PTR,
NULL, 0),
OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL),
OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL),
OSSL_PARAM_END
};
static const OSSL_PARAM *rsa_gettable_ctx_params(ossl_unused void *vprsactx,
ossl_unused void *provctx)
{
return known_gettable_ctx_params;
}
static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
const OSSL_PARAM *p;
char mdname[OSSL_MAX_NAME_SIZE];
char mdprops[OSSL_MAX_PROPQUERY_SIZE] = { '\0' };
char *str = NULL;
if (prsactx == NULL)
return 0;
if (params == NULL)
return 1;
p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST);
if (p != NULL) {
str = mdname;
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdname)))
return 0;
p = OSSL_PARAM_locate_const(params,
OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS);
if (p != NULL) {
str = mdprops;
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
return 0;
}
EVP_MD_free(prsactx->oaep_md);
prsactx->oaep_md = EVP_MD_fetch(prsactx->libctx, mdname, mdprops);
if (prsactx->oaep_md == NULL)
return 0;
}
p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE);
if (p != NULL) {
int pad_mode = 0;
switch (p->data_type) {
case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
if (!OSSL_PARAM_get_int(p, &pad_mode))
return 0;
break;
case OSSL_PARAM_UTF8_STRING:
{
int i;
if (p->data == NULL)
return 0;
for (i = 0; padding_item[i].id != 0; i++) {
if (strcmp(p->data, padding_item[i].ptr) == 0) {
pad_mode = padding_item[i].id;
break;
}
}
}
break;
default:
return 0;
}
/*
* PSS padding is for signatures only so is not compatible with
* asymmetric cipher use.
*/
if (pad_mode == RSA_PKCS1_PSS_PADDING)
return 0;
if (pad_mode == RSA_PKCS1_OAEP_PADDING && prsactx->oaep_md == NULL) {
prsactx->oaep_md = EVP_MD_fetch(prsactx->libctx, "SHA1", mdprops);
if (prsactx->oaep_md == NULL)
return 0;
}
prsactx->pad_mode = pad_mode;
}
p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST);
if (p != NULL) {
str = mdname;
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdname)))
return 0;
p = OSSL_PARAM_locate_const(params,
OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS);
if (p != NULL) {
str = mdprops;
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
return 0;
} else {
str = NULL;
}
EVP_MD_free(prsactx->mgf1_md);
prsactx->mgf1_md = EVP_MD_fetch(prsactx->libctx, mdname, str);
if (prsactx->mgf1_md == NULL)
return 0;
}
p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL);
if (p != NULL) {
void *tmp_label = NULL;
size_t tmp_labellen;
if (!OSSL_PARAM_get_octet_string(p, &tmp_label, 0, &tmp_labellen))
return 0;
OPENSSL_free(prsactx->oaep_label);
prsactx->oaep_label = (unsigned char *)tmp_label;
prsactx->oaep_labellen = tmp_labellen;
}
p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION);
if (p != NULL) {
unsigned int client_version;
if (!OSSL_PARAM_get_uint(p, &client_version))
return 0;
prsactx->client_version = client_version;
}
p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION);
if (p != NULL) {
unsigned int alt_version;
if (!OSSL_PARAM_get_uint(p, &alt_version))
return 0;
prsactx->alt_version = alt_version;
}
return 1;
}
static const OSSL_PARAM known_settable_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS, NULL, 0),
OSSL_PARAM_octet_string(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, NULL, 0),
OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL),
OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL),
OSSL_PARAM_END
};
static const OSSL_PARAM *rsa_settable_ctx_params(ossl_unused void *vprsactx,
ossl_unused void *provctx)
{
return known_settable_ctx_params;
}
const OSSL_DISPATCH ossl_rsa_asym_cipher_functions[] = {
{ OSSL_FUNC_ASYM_CIPHER_NEWCTX, (void (*)(void))rsa_newctx },
{ OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT, (void (*)(void))rsa_encrypt_init },
{ OSSL_FUNC_ASYM_CIPHER_ENCRYPT, (void (*)(void))rsa_encrypt },
{ OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT, (void (*)(void))rsa_decrypt_init },
{ OSSL_FUNC_ASYM_CIPHER_DECRYPT, (void (*)(void))rsa_decrypt },
{ OSSL_FUNC_ASYM_CIPHER_FREECTX, (void (*)(void))rsa_freectx },
{ OSSL_FUNC_ASYM_CIPHER_DUPCTX, (void (*)(void))rsa_dupctx },
{ OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS,
(void (*)(void))rsa_get_ctx_params },
{ OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS,
(void (*)(void))rsa_gettable_ctx_params },
{ OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS,
(void (*)(void))rsa_set_ctx_params },
{ OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS,
(void (*)(void))rsa_settable_ctx_params },
{ 0, NULL }
};
diff --git a/providers/implementations/ciphers/cipher_tdes_common.c b/providers/implementations/ciphers/cipher_tdes_common.c
index 346aec05a1cc..af2f5b98415c 100644
--- a/providers/implementations/ciphers/cipher_tdes_common.c
+++ b/providers/implementations/ciphers/cipher_tdes_common.c
@@ -1,149 +1,148 @@
/*
- * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/*
* DES low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include <openssl/rand.h>
#include <openssl/proverr.h>
#include "prov/ciphercommon.h"
#include "cipher_tdes.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
void *ossl_tdes_newctx(void *provctx, int mode, size_t kbits, size_t blkbits,
size_t ivbits, uint64_t flags, const PROV_CIPHER_HW *hw)
{
PROV_TDES_CTX *tctx;
if (!ossl_prov_is_running())
return NULL;
tctx = OPENSSL_zalloc(sizeof(*tctx));
if (tctx != NULL)
ossl_cipher_generic_initkey(tctx, kbits, blkbits, ivbits, mode, flags,
hw, provctx);
return tctx;
}
void *ossl_tdes_dupctx(void *ctx)
{
PROV_TDES_CTX *in = (PROV_TDES_CTX *)ctx;
PROV_TDES_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;
}
in->base.hw->copyctx(&ret->base, &in->base);
return ret;
}
void ossl_tdes_freectx(void *vctx)
{
PROV_TDES_CTX *ctx = (PROV_TDES_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static int tdes_init(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[], int enc)
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
ctx->num = 0;
ctx->bufsz = 0;
ctx->enc = enc;
if (iv != NULL) {
if (!ossl_cipher_generic_initiv(ctx, iv, ivlen))
return 0;
} else if (ctx->iv_set
&& (ctx->mode == EVP_CIPH_CBC_MODE
|| ctx->mode == EVP_CIPH_CFB_MODE
|| ctx->mode == EVP_CIPH_OFB_MODE)) {
/* reset IV to keep compatibility with 1.1.1 */
memcpy(ctx->iv, ctx->oiv, ctx->ivlen);
}
if (key != NULL) {
if (keylen != ctx->keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
if (!ctx->hw->init(ctx, key, ctx->keylen))
return 0;
}
return ossl_cipher_generic_set_ctx_params(ctx, params);
}
int ossl_tdes_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return tdes_init(vctx, key, keylen, iv, ivlen, params, 1);
}
int ossl_tdes_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return tdes_init(vctx, key, keylen, iv, ivlen, params, 0);
}
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(ossl_tdes)
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_RANDOM_KEY, NULL, 0),
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(ossl_tdes)
static int tdes_generatekey(PROV_CIPHER_CTX *ctx, void *ptr)
{
DES_cblock *deskey = ptr;
size_t kl = ctx->keylen;
if (kl == 0 || RAND_priv_bytes_ex(ctx->libctx, ptr, kl, 0) <= 0)
return 0;
DES_set_odd_parity(deskey);
- if (kl >= 16)
+ if (kl >= 16) {
DES_set_odd_parity(deskey + 1);
- if (kl >= 24) {
- DES_set_odd_parity(deskey + 2);
- return 1;
+ if (kl >= 24)
+ DES_set_odd_parity(deskey + 2);
}
- return 0;
+ return 1;
}
int ossl_tdes_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
OSSL_PARAM *p;
if (!ossl_cipher_generic_get_ctx_params(vctx, params))
return 0;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_RANDOM_KEY);
if (p != NULL && !tdes_generatekey(ctx, p->data)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY);
return 0;
}
return 1;
}
diff --git a/providers/implementations/kdfs/hkdf.c b/providers/implementations/kdfs/hkdf.c
index dfa7786bde0c..25819ea23977 100644
--- a/providers/implementations/kdfs/hkdf.c
+++ b/providers/implementations/kdfs/hkdf.c
@@ -1,783 +1,783 @@
/*
- * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/*
* 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);
}
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_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 = (done_len + dig_len > okm_len) ?
+ 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,
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/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c
index 3f1dc9e191be..a37cbbdba809 100644
--- a/providers/implementations/keymgmt/ec_kmgmt.c
+++ b/providers/implementations/keymgmt/ec_kmgmt.c
@@ -1,1467 +1,1467 @@
/*
* 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
*/
/*
* ECDH/ECDSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <string.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/proverr.h>
#include "crypto/bn.h"
#include "crypto/ec.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#include "prov/provider_ctx.h"
#include "internal/param_build_set.h"
#ifndef FIPS_MODULE
# ifndef OPENSSL_NO_SM2
# include "crypto/sm2.h"
# endif
#endif
static OSSL_FUNC_keymgmt_new_fn ec_newdata;
static OSSL_FUNC_keymgmt_gen_init_fn ec_gen_init;
static OSSL_FUNC_keymgmt_gen_set_template_fn ec_gen_set_template;
static OSSL_FUNC_keymgmt_gen_set_params_fn ec_gen_set_params;
static OSSL_FUNC_keymgmt_gen_settable_params_fn ec_gen_settable_params;
static OSSL_FUNC_keymgmt_gen_fn ec_gen;
static OSSL_FUNC_keymgmt_gen_cleanup_fn ec_gen_cleanup;
static OSSL_FUNC_keymgmt_load_fn ec_load;
static OSSL_FUNC_keymgmt_free_fn ec_freedata;
static OSSL_FUNC_keymgmt_get_params_fn ec_get_params;
static OSSL_FUNC_keymgmt_gettable_params_fn ec_gettable_params;
static OSSL_FUNC_keymgmt_set_params_fn ec_set_params;
static OSSL_FUNC_keymgmt_settable_params_fn ec_settable_params;
static OSSL_FUNC_keymgmt_has_fn ec_has;
static OSSL_FUNC_keymgmt_match_fn ec_match;
static OSSL_FUNC_keymgmt_validate_fn ec_validate;
static OSSL_FUNC_keymgmt_import_fn ec_import;
static OSSL_FUNC_keymgmt_import_types_fn ec_import_types;
static OSSL_FUNC_keymgmt_export_fn ec_export;
static OSSL_FUNC_keymgmt_export_types_fn ec_export_types;
static OSSL_FUNC_keymgmt_query_operation_name_fn ec_query_operation_name;
static OSSL_FUNC_keymgmt_dup_fn ec_dup;
#ifndef FIPS_MODULE
# ifndef OPENSSL_NO_SM2
static OSSL_FUNC_keymgmt_new_fn sm2_newdata;
static OSSL_FUNC_keymgmt_gen_init_fn sm2_gen_init;
static OSSL_FUNC_keymgmt_gen_fn sm2_gen;
static OSSL_FUNC_keymgmt_get_params_fn sm2_get_params;
static OSSL_FUNC_keymgmt_gettable_params_fn sm2_gettable_params;
static OSSL_FUNC_keymgmt_settable_params_fn sm2_settable_params;
static OSSL_FUNC_keymgmt_import_fn sm2_import;
static OSSL_FUNC_keymgmt_query_operation_name_fn sm2_query_operation_name;
static OSSL_FUNC_keymgmt_validate_fn sm2_validate;
# endif
#endif
#define EC_DEFAULT_MD "SHA256"
#define EC_POSSIBLE_SELECTIONS \
(OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)
#define SM2_DEFAULT_MD "SM3"
static
const char *ec_query_operation_name(int operation_id)
{
switch (operation_id) {
case OSSL_OP_KEYEXCH:
return "ECDH";
case OSSL_OP_SIGNATURE:
return "ECDSA";
}
return NULL;
}
#ifndef FIPS_MODULE
# ifndef OPENSSL_NO_SM2
static
const char *sm2_query_operation_name(int operation_id)
{
switch (operation_id) {
case OSSL_OP_SIGNATURE:
return "SM2";
}
return NULL;
}
# endif
#endif
/*
* Callers of key_to_params MUST make sure that domparams_to_params is also
* called!
*
* This function only exports the bare keypair, domain parameters and other
* parameters are exported separately.
*/
static ossl_inline
int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl,
OSSL_PARAM params[], int include_private,
unsigned char **pub_key)
{
BIGNUM *x = NULL, *y = NULL;
const BIGNUM *priv_key = NULL;
const EC_POINT *pub_point = NULL;
const EC_GROUP *ecg = NULL;
size_t pub_key_len = 0;
int ret = 0;
BN_CTX *bnctx = NULL;
if (eckey == NULL
|| (ecg = EC_KEY_get0_group(eckey)) == NULL)
return 0;
priv_key = EC_KEY_get0_private_key(eckey);
pub_point = EC_KEY_get0_public_key(eckey);
if (pub_point != NULL) {
OSSL_PARAM *p = NULL, *px = NULL, *py = NULL;
/*
* EC_POINT_point2buf() can generate random numbers in some
* implementations so we need to ensure we use the correct libctx.
*/
bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eckey));
if (bnctx == NULL)
goto err;
/* If we are doing a get then check first before decoding the point */
if (tmpl == NULL) {
p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY);
px = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_X);
py = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_Y);
}
if (p != NULL || tmpl != NULL) {
/* convert pub_point to a octet string according to the SECG standard */
point_conversion_form_t format = EC_KEY_get_conv_form(eckey);
if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point,
format,
pub_key, bnctx)) == 0
|| !ossl_param_build_set_octet_string(tmpl, p,
OSSL_PKEY_PARAM_PUB_KEY,
*pub_key, pub_key_len))
goto err;
}
if (px != NULL || py != NULL) {
if (px != NULL) {
x = BN_CTX_get(bnctx);
if (x == NULL)
goto err;
}
if (py != NULL) {
y = BN_CTX_get(bnctx);
if (y == NULL)
goto err;
}
if (!EC_POINT_get_affine_coordinates(ecg, pub_point, x, y, bnctx))
goto err;
if (px != NULL
&& !ossl_param_build_set_bn(tmpl, px,
OSSL_PKEY_PARAM_EC_PUB_X, x))
goto err;
if (py != NULL
&& !ossl_param_build_set_bn(tmpl, py,
OSSL_PKEY_PARAM_EC_PUB_Y, y))
goto err;
}
}
if (priv_key != NULL && include_private) {
size_t sz;
int ecbits;
/*
* 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.
*/
ecbits = EC_GROUP_order_bits(ecg);
if (ecbits <= 0)
goto err;
sz = (ecbits + 7 ) / 8;
if (!ossl_param_build_set_bn_pad(tmpl, params,
OSSL_PKEY_PARAM_PRIV_KEY,
priv_key, sz))
goto err;
}
ret = 1;
err:
BN_CTX_free(bnctx);
return ret;
}
static ossl_inline
int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl,
OSSL_PARAM params[])
{
int ecdh_cofactor_mode = 0, group_check = 0;
const char *name = NULL;
point_conversion_form_t format;
if (ec == NULL)
return 0;
format = EC_KEY_get_conv_form(ec);
name = ossl_ec_pt_format_id2name((int)format);
if (name != NULL
&& !ossl_param_build_set_utf8_string(tmpl, params,
OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
name))
return 0;
group_check = EC_KEY_get_flags(ec) & EC_FLAG_CHECK_NAMED_GROUP_MASK;
name = ossl_ec_check_group_type_id2name(group_check);
if (name != NULL
&& !ossl_param_build_set_utf8_string(tmpl, params,
OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE,
name))
return 0;
if ((EC_KEY_get_enc_flags(ec) & EC_PKEY_NO_PUBKEY) != 0
&& !ossl_param_build_set_int(tmpl, params,
OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 0))
return 0;
ecdh_cofactor_mode =
(EC_KEY_get_flags(ec) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
return ossl_param_build_set_int(tmpl, params,
OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
ecdh_cofactor_mode);
}
static
void *ec_newdata(void *provctx)
{
if (!ossl_prov_is_running())
return NULL;
return EC_KEY_new_ex(PROV_LIBCTX_OF(provctx), NULL);
}
#ifndef FIPS_MODULE
# ifndef OPENSSL_NO_SM2
static
void *sm2_newdata(void *provctx)
{
if (!ossl_prov_is_running())
return NULL;
return EC_KEY_new_by_curve_name_ex(PROV_LIBCTX_OF(provctx), NULL, NID_sm2);
}
# endif
#endif
static
void ec_freedata(void *keydata)
{
EC_KEY_free(keydata);
}
static
int ec_has(const void *keydata, int selection)
{
const EC_KEY *ec = keydata;
int ok = 1;
if (!ossl_prov_is_running() || ec == NULL)
return 0;
if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
return 1; /* the selection is not missing */
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
ok = ok && (EC_KEY_get0_public_key(ec) != NULL);
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = ok && (EC_KEY_get0_private_key(ec) != NULL);
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ok = ok && (EC_KEY_get0_group(ec) != NULL);
/*
* We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be
* available, so no extra check is needed other than the previous one
* against EC_POSSIBLE_SELECTIONS.
*/
return ok;
}
static int ec_match(const void *keydata1, const void *keydata2, int selection)
{
const EC_KEY *ec1 = keydata1;
const EC_KEY *ec2 = keydata2;
const EC_GROUP *group_a = EC_KEY_get0_group(ec1);
const EC_GROUP *group_b = EC_KEY_get0_group(ec2);
BN_CTX *ctx = NULL;
int ok = 1;
if (!ossl_prov_is_running())
return 0;
ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec1));
if (ctx == NULL)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ok = ok && group_a != NULL && group_b != NULL
&& EC_GROUP_cmp(group_a, group_b, ctx) == 0;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
int key_checked = 0;
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
const EC_POINT *pa = EC_KEY_get0_public_key(ec1);
const EC_POINT *pb = EC_KEY_get0_public_key(ec2);
if (pa != NULL && pb != NULL) {
ok = ok && EC_POINT_cmp(group_b, pa, pb, ctx) == 0;
key_checked = 1;
}
}
if (!key_checked
&& (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
const BIGNUM *pa = EC_KEY_get0_private_key(ec1);
const BIGNUM *pb = EC_KEY_get0_private_key(ec2);
if (pa != NULL && pb != NULL) {
ok = ok && BN_cmp(pa, pb) == 0;
key_checked = 1;
}
}
ok = ok && key_checked;
}
BN_CTX_free(ctx);
return ok;
}
static int common_check_sm2(const EC_KEY *ec, int sm2_wanted)
{
const EC_GROUP *ecg = NULL;
/*
* sm2_wanted: import the keys or domparams only on SM2 Curve
* !sm2_wanted: import the keys or domparams only not on SM2 Curve
*/
if ((ecg = EC_KEY_get0_group(ec)) == NULL
|| (sm2_wanted ^ (EC_GROUP_get_curve_name(ecg) == NID_sm2)))
return 0;
return 1;
}
static
int common_import(void *keydata, int selection, const OSSL_PARAM params[],
int sm2_wanted)
{
EC_KEY *ec = keydata;
int ok = 1;
if (!ossl_prov_is_running() || ec == NULL)
return 0;
/*
* In this implementation, we can export/import only keydata in the
* following combinations:
* - domain parameters (+optional other params)
* - public key with associated domain parameters (+optional other params)
* - private key with associated domain parameters and optional public key
* (+optional other params)
*
* This means:
* - domain parameters must always be requested
* - private key must be requested alongside public key
* - other parameters are always optional
*/
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
return 0;
ok = ok && ossl_ec_group_fromdata(ec, params);
if (!common_check_sm2(ec, sm2_wanted))
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
int include_private =
selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
ok = ok && ossl_ec_key_fromdata(ec, params, include_private);
}
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
ok = ok && ossl_ec_key_otherparams_fromdata(ec, params);
return ok;
}
static
int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
{
return common_import(keydata, selection, params, 0);
}
#ifndef FIPS_MODULE
# ifndef OPENSSL_NO_SM2
static
int sm2_import(void *keydata, int selection, const OSSL_PARAM params[])
{
return common_import(keydata, selection, params, 1);
}
# endif
#endif
static
int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
void *cbarg)
{
EC_KEY *ec = keydata;
OSSL_PARAM_BLD *tmpl = NULL;
OSSL_PARAM *params = NULL;
unsigned char *pub_key = NULL, *genbuf = NULL;
BN_CTX *bnctx = NULL;
int ok = 1;
if (!ossl_prov_is_running() || ec == NULL)
return 0;
/*
* In this implementation, we can export/import only keydata in the
* following combinations:
* - domain parameters (+optional other params)
* - public key with associated domain parameters (+optional other params)
* - private key with associated public key and domain parameters
* (+optional other params)
*
* This means:
* - domain parameters must always be requested
* - private key must be requested alongside public key
* - other parameters are always optional
*/
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
&& (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
return 0;
tmpl = OSSL_PARAM_BLD_new();
if (tmpl == NULL)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec));
if (bnctx == NULL) {
ok = 0;
goto end;
}
BN_CTX_start(bnctx);
ok = ok && ossl_ec_group_todata(EC_KEY_get0_group(ec), tmpl, NULL,
ossl_ec_key_get_libctx(ec),
ossl_ec_key_get0_propq(ec),
bnctx, &genbuf);
}
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
int include_private =
selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
ok = ok && key_to_params(ec, tmpl, NULL, include_private, &pub_key);
}
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
ok = ok && otherparams_to_params(ec, tmpl, NULL);
if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
ok = 0;
goto end;
}
ok = param_cb(params, cbarg);
OSSL_PARAM_free(params);
end:
OSSL_PARAM_BLD_free(tmpl);
OPENSSL_free(pub_key);
OPENSSL_free(genbuf);
BN_CTX_end(bnctx);
BN_CTX_free(bnctx);
return ok;
}
/* IMEXPORT = IMPORT + EXPORT */
# define EC_IMEXPORTABLE_DOM_PARAMETERS \
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), \
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), \
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),\
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0), \
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0), \
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL)
# define EC_IMEXPORTABLE_PUBLIC_KEY \
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
# define EC_IMEXPORTABLE_PRIVATE_KEY \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
# define EC_IMEXPORTABLE_OTHER_PARAMETERS \
OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL)
/*
* Include all the possible combinations of OSSL_PARAM arrays for
* ec_imexport_types().
*
* They are in a separate file as it is ~100 lines of unreadable and
* uninteresting machine generated stuff.
*/
#include "ec_kmgmt_imexport.inc"
static ossl_inline
const OSSL_PARAM *ec_imexport_types(int selection)
{
int type_select = 0;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
type_select += 1;
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
type_select += 2;
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
type_select += 4;
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
type_select += 8;
return ec_types[type_select];
}
static
const OSSL_PARAM *ec_import_types(int selection)
{
return ec_imexport_types(selection);
}
static
const OSSL_PARAM *ec_export_types(int selection)
{
return ec_imexport_types(selection);
}
static int ec_get_ecm_params(const EC_GROUP *group, OSSL_PARAM params[])
{
#ifdef OPENSSL_NO_EC2M
return 1;
#else
int ret = 0, m;
unsigned int k1 = 0, k2 = 0, k3 = 0;
int basis_nid;
const char *basis_name = NULL;
int fid = EC_GROUP_get_field_type(group);
if (fid != NID_X9_62_characteristic_two_field)
return 1;
basis_nid = EC_GROUP_get_basis_type(group);
if (basis_nid == NID_X9_62_tpBasis)
basis_name = SN_X9_62_tpBasis;
else if (basis_nid == NID_X9_62_ppBasis)
basis_name = SN_X9_62_ppBasis;
else
goto err;
m = EC_GROUP_get_degree(group);
if (!ossl_param_build_set_int(NULL, params, OSSL_PKEY_PARAM_EC_CHAR2_M, m)
|| !ossl_param_build_set_utf8_string(NULL, params,
OSSL_PKEY_PARAM_EC_CHAR2_TYPE,
basis_name))
goto err;
if (basis_nid == NID_X9_62_tpBasis) {
if (!EC_GROUP_get_trinomial_basis(group, &k1)
|| !ossl_param_build_set_int(NULL, params,
OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS,
(int)k1))
goto err;
} else {
if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)
|| !ossl_param_build_set_int(NULL, params,
OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, (int)k1)
|| !ossl_param_build_set_int(NULL, params,
OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, (int)k2)
|| !ossl_param_build_set_int(NULL, params,
OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, (int)k3))
goto err;
}
ret = 1;
err:
return ret;
#endif /* OPENSSL_NO_EC2M */
}
static
int common_get_params(void *key, OSSL_PARAM params[], int sm2)
{
int ret = 0;
EC_KEY *eck = key;
const EC_GROUP *ecg = NULL;
OSSL_PARAM *p;
unsigned char *pub_key = NULL, *genbuf = NULL;
OSSL_LIB_CTX *libctx;
const char *propq;
BN_CTX *bnctx = NULL;
ecg = EC_KEY_get0_group(eck);
if (ecg == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET);
return 0;
}
libctx = ossl_ec_key_get_libctx(eck);
propq = ossl_ec_key_get0_propq(eck);
bnctx = BN_CTX_new_ex(libctx);
if (bnctx == NULL)
return 0;
BN_CTX_start(bnctx);
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
&& !OSSL_PARAM_set_int(p, ECDSA_size(eck)))
goto err;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
&& !OSSL_PARAM_set_int(p, EC_GROUP_order_bits(ecg)))
goto err;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) {
int ecbits, sec_bits;
ecbits = EC_GROUP_order_bits(ecg);
/*
* The following estimates are based on the values published
* in Table 2 of "NIST Special Publication 800-57 Part 1 Revision 4"
* at http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 .
*
* Note that the above reference explicitly categorizes algorithms in a
* discrete set of values {80, 112, 128, 192, 256}, and that it is
* relevant only for NIST approved Elliptic Curves, while OpenSSL
* applies the same logic also to other curves.
*
* Classifications produced by other standardazing bodies might differ,
* so the results provided for "bits of security" by this provider are
* to be considered merely indicative, and it is the users'
* responsibility to compare these values against the normative
* references that may be relevant for their intent and purposes.
*/
if (ecbits >= 512)
sec_bits = 256;
else if (ecbits >= 384)
sec_bits = 192;
else if (ecbits >= 256)
sec_bits = 128;
else if (ecbits >= 224)
sec_bits = 112;
else if (ecbits >= 160)
sec_bits = 80;
else
sec_bits = ecbits / 2;
if (!OSSL_PARAM_set_int(p, sec_bits))
goto err;
}
if ((p = OSSL_PARAM_locate(params,
OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS))
!= NULL) {
int explicitparams = EC_KEY_decoded_from_explicit_params(eck);
if (explicitparams < 0
|| !OSSL_PARAM_set_int(p, explicitparams))
goto err;
}
if (!sm2) {
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
&& !OSSL_PARAM_set_utf8_string(p, EC_DEFAULT_MD))
goto err;
} else {
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
&& !OSSL_PARAM_set_utf8_string(p, SM2_DEFAULT_MD))
goto err;
}
/* SM2 doesn't support this PARAM */
if (!sm2) {
p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
if (p != NULL) {
int ecdh_cofactor_mode = 0;
ecdh_cofactor_mode =
(EC_KEY_get_flags(eck) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
if (!OSSL_PARAM_set_int(p, ecdh_cofactor_mode))
goto err;
}
}
if ((p = OSSL_PARAM_locate(params,
OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) {
const EC_POINT *ecp = EC_KEY_get0_public_key(key);
if (ecp == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
goto err;
}
p->return_size = EC_POINT_point2oct(ecg, ecp,
POINT_CONVERSION_UNCOMPRESSED,
- p->data, p->return_size, bnctx);
+ p->data, p->data_size, bnctx);
if (p->return_size == 0)
goto err;
}
ret = ec_get_ecm_params(ecg, params)
&& ossl_ec_group_todata(ecg, NULL, params, libctx, propq, bnctx,
&genbuf)
&& key_to_params(eck, NULL, params, 1, &pub_key)
&& otherparams_to_params(eck, NULL, params);
err:
OPENSSL_free(genbuf);
OPENSSL_free(pub_key);
BN_CTX_end(bnctx);
BN_CTX_free(bnctx);
return ret;
}
static
int ec_get_params(void *key, OSSL_PARAM params[])
{
return common_get_params(key, params, 0);
}
#ifndef OPENSSL_NO_EC2M
# define EC2M_GETTABLE_DOM_PARAMS \
OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_M, NULL), \
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_CHAR2_TYPE, NULL, 0), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS, NULL), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, NULL), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, NULL), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, NULL),
#else
# define EC2M_GETTABLE_DOM_PARAMS
#endif
static const OSSL_PARAM ec_known_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_DEFAULT_DIGEST, NULL, 0),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL),
EC_IMEXPORTABLE_DOM_PARAMETERS,
EC2M_GETTABLE_DOM_PARAMS
EC_IMEXPORTABLE_PUBLIC_KEY,
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),
EC_IMEXPORTABLE_PRIVATE_KEY,
EC_IMEXPORTABLE_OTHER_PARAMETERS,
OSSL_PARAM_END
};
static
const OSSL_PARAM *ec_gettable_params(void *provctx)
{
return ec_known_gettable_params;
}
static const OSSL_PARAM ec_known_settable_params[] = {
OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),
OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, NULL, 0),
OSSL_PARAM_END
};
static
const OSSL_PARAM *ec_settable_params(void *provctx)
{
return ec_known_settable_params;
}
static
int ec_set_params(void *key, const OSSL_PARAM params[])
{
EC_KEY *eck = key;
const OSSL_PARAM *p;
if (key == NULL)
return 0;
if (params == NULL)
return 1;
if (!ossl_ec_group_set_params((EC_GROUP *)EC_KEY_get0_group(key), params))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
if (p != NULL) {
BN_CTX *ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(key));
int ret = 1;
if (ctx == NULL
|| p->data_type != OSSL_PARAM_OCTET_STRING
|| !EC_KEY_oct2key(key, p->data, p->data_size, ctx))
ret = 0;
BN_CTX_free(ctx);
if (!ret)
return 0;
}
return ossl_ec_key_otherparams_fromdata(eck, params);
}
#ifndef FIPS_MODULE
# ifndef OPENSSL_NO_SM2
static
int sm2_get_params(void *key, OSSL_PARAM params[])
{
return common_get_params(key, params, 1);
}
static const OSSL_PARAM sm2_known_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_DEFAULT_DIGEST, NULL, 0),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL),
EC_IMEXPORTABLE_DOM_PARAMETERS,
EC_IMEXPORTABLE_PUBLIC_KEY,
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),
EC_IMEXPORTABLE_PRIVATE_KEY,
OSSL_PARAM_END
};
static
const OSSL_PARAM *sm2_gettable_params(ossl_unused void *provctx)
{
return sm2_known_gettable_params;
}
static const OSSL_PARAM sm2_known_settable_params[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
OSSL_PARAM_END
};
static
const OSSL_PARAM *sm2_settable_params(ossl_unused void *provctx)
{
return sm2_known_settable_params;
}
static
int sm2_validate(const void *keydata, int selection, int checktype)
{
const EC_KEY *eck = keydata;
int ok = 1;
BN_CTX *ctx = NULL;
if (!ossl_prov_is_running())
return 0;
if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
return 1; /* nothing to validate */
ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eck));
if (ctx == NULL)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
ok = ok && ossl_ec_key_public_check_quick(eck, ctx);
else
ok = ok && ossl_ec_key_public_check(eck, ctx);
}
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = ok && ossl_sm2_key_private_check(eck);
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
ok = ok && ossl_ec_key_pairwise_check(eck, ctx);
BN_CTX_free(ctx);
return ok;
}
# endif
#endif
static
int ec_validate(const void *keydata, int selection, int checktype)
{
const EC_KEY *eck = keydata;
int ok = 1;
BN_CTX *ctx = NULL;
if (!ossl_prov_is_running())
return 0;
if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
return 1; /* nothing to validate */
ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eck));
if (ctx == NULL)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
int flags = EC_KEY_get_flags(eck);
if ((flags & EC_FLAG_CHECK_NAMED_GROUP) != 0)
ok = ok && EC_GROUP_check_named_curve(EC_KEY_get0_group(eck),
(flags & EC_FLAG_CHECK_NAMED_GROUP_NIST) != 0, ctx) > 0;
else
ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
}
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
ok = ok && ossl_ec_key_public_check_quick(eck, ctx);
else
ok = ok && ossl_ec_key_public_check(eck, ctx);
}
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = ok && ossl_ec_key_private_check(eck);
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
ok = ok && ossl_ec_key_pairwise_check(eck, ctx);
BN_CTX_free(ctx);
return ok;
}
struct ec_gen_ctx {
OSSL_LIB_CTX *libctx;
char *group_name;
char *encoding;
char *pt_format;
char *group_check;
char *field_type;
BIGNUM *p, *a, *b, *order, *cofactor;
unsigned char *gen, *seed;
size_t gen_len, seed_len;
int selection;
int ecdh_mode;
EC_GROUP *gen_group;
};
static void *ec_gen_init(void *provctx, int selection,
const OSSL_PARAM params[])
{
OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
struct ec_gen_ctx *gctx = NULL;
if (!ossl_prov_is_running() || (selection & (EC_POSSIBLE_SELECTIONS)) == 0)
return NULL;
if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
gctx->libctx = libctx;
gctx->selection = selection;
gctx->ecdh_mode = 0;
if (!ec_gen_set_params(gctx, params)) {
OPENSSL_free(gctx);
gctx = NULL;
}
}
return gctx;
}
#ifndef FIPS_MODULE
# ifndef OPENSSL_NO_SM2
static void *sm2_gen_init(void *provctx, int selection,
const OSSL_PARAM params[])
{
struct ec_gen_ctx *gctx = ec_gen_init(provctx, selection, params);
if (gctx != NULL) {
if (gctx->group_name != NULL)
return gctx;
if ((gctx->group_name = OPENSSL_strdup("sm2")) != NULL)
return gctx;
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
ec_gen_cleanup(gctx);
}
return NULL;
}
# endif
#endif
static int ec_gen_set_group(void *genctx, const EC_GROUP *src)
{
struct ec_gen_ctx *gctx = genctx;
EC_GROUP *group;
group = EC_GROUP_dup(src);
if (group == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);
return 0;
}
EC_GROUP_free(gctx->gen_group);
gctx->gen_group = group;
return 1;
}
static int ec_gen_set_template(void *genctx, void *templ)
{
struct ec_gen_ctx *gctx = genctx;
EC_KEY *ec = templ;
const EC_GROUP *ec_group;
if (!ossl_prov_is_running() || gctx == NULL || ec == NULL)
return 0;
if ((ec_group = EC_KEY_get0_group(ec)) == NULL)
return 0;
return ec_gen_set_group(gctx, ec_group);
}
#define COPY_INT_PARAM(params, key, val) \
p = OSSL_PARAM_locate_const(params, key); \
if (p != NULL && !OSSL_PARAM_get_int(p, &val)) \
goto err;
#define COPY_UTF8_PARAM(params, key, val) \
p = OSSL_PARAM_locate_const(params, key); \
if (p != NULL) { \
if (p->data_type != OSSL_PARAM_UTF8_STRING) \
goto err; \
OPENSSL_free(val); \
val = OPENSSL_strdup(p->data); \
if (val == NULL) \
goto err; \
}
#define COPY_OCTET_PARAM(params, key, val, len) \
p = OSSL_PARAM_locate_const(params, key); \
if (p != NULL) { \
if (p->data_type != OSSL_PARAM_OCTET_STRING) \
goto err; \
OPENSSL_free(val); \
len = p->data_size; \
val = OPENSSL_memdup(p->data, p->data_size); \
if (val == NULL) \
goto err; \
}
#define COPY_BN_PARAM(params, key, bn) \
p = OSSL_PARAM_locate_const(params, key); \
if (p != NULL) { \
if (bn == NULL) \
bn = BN_new(); \
if (bn == NULL || !OSSL_PARAM_get_BN(p, &bn)) \
goto err; \
}
static int ec_gen_set_params(void *genctx, const OSSL_PARAM params[])
{
int ret = 0;
struct ec_gen_ctx *gctx = genctx;
const OSSL_PARAM *p;
EC_GROUP *group = NULL;
COPY_INT_PARAM(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, gctx->ecdh_mode);
COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_GROUP_NAME, gctx->group_name);
COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE, gctx->field_type);
COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_ENCODING, gctx->encoding);
COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, gctx->pt_format);
COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, gctx->group_check);
COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_P, gctx->p);
COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_A, gctx->a);
COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_B, gctx->b);
COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_ORDER, gctx->order);
COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_COFACTOR, gctx->cofactor);
COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_SEED, gctx->seed, gctx->seed_len);
COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_GENERATOR, gctx->gen,
gctx->gen_len);
ret = 1;
err:
EC_GROUP_free(group);
return ret;
}
static int ec_gen_set_group_from_params(struct ec_gen_ctx *gctx)
{
int ret = 0;
OSSL_PARAM_BLD *bld;
OSSL_PARAM *params = NULL;
EC_GROUP *group = NULL;
bld = OSSL_PARAM_BLD_new();
if (bld == NULL)
return 0;
if (gctx->encoding != NULL
&& !OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_ENCODING,
gctx->encoding, 0))
goto err;
if (gctx->pt_format != NULL
&& !OSSL_PARAM_BLD_push_utf8_string(bld,
OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
gctx->pt_format, 0))
goto err;
if (gctx->group_name != NULL) {
if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME,
gctx->group_name, 0))
goto err;
/* Ignore any other parameters if there is a group name */
goto build;
} else if (gctx->field_type != NULL) {
if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_FIELD_TYPE,
gctx->field_type, 0))
goto err;
} else {
goto err;
}
if (gctx->p == NULL
|| gctx->a == NULL
|| gctx->b == NULL
|| gctx->order == NULL
|| !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_P, gctx->p)
|| !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_A, gctx->a)
|| !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_B, gctx->b)
|| !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_ORDER, gctx->order))
goto err;
if (gctx->cofactor != NULL
&& !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_COFACTOR,
gctx->cofactor))
goto err;
if (gctx->seed != NULL
&& !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_SEED,
gctx->seed, gctx->seed_len))
goto err;
if (gctx->gen == NULL
|| !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_GENERATOR,
gctx->gen, gctx->gen_len))
goto err;
build:
params = OSSL_PARAM_BLD_to_param(bld);
if (params == NULL)
goto err;
group = EC_GROUP_new_from_params(params, gctx->libctx, NULL);
if (group == NULL)
goto err;
EC_GROUP_free(gctx->gen_group);
gctx->gen_group = group;
ret = 1;
err:
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(bld);
return ret;
}
static const OSSL_PARAM *ec_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_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0),
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0),
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0),
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0),
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0),
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),
OSSL_PARAM_END
};
return settable;
}
static int ec_gen_assign_group(EC_KEY *ec, EC_GROUP *group)
{
if (group == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET);
return 0;
}
return EC_KEY_set_group(ec, group) > 0;
}
/*
* The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
*/
static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
{
struct ec_gen_ctx *gctx = genctx;
EC_KEY *ec = NULL;
int ret = 0;
if (!ossl_prov_is_running()
|| gctx == NULL
|| (ec = EC_KEY_new_ex(gctx->libctx, NULL)) == NULL)
return NULL;
if (gctx->gen_group == NULL) {
if (!ec_gen_set_group_from_params(gctx))
goto err;
} else {
if (gctx->encoding != NULL) {
int flags = ossl_ec_encoding_name2id(gctx->encoding);
if (flags < 0)
goto err;
EC_GROUP_set_asn1_flag(gctx->gen_group, flags);
}
if (gctx->pt_format != NULL) {
int format = ossl_ec_pt_format_name2id(gctx->pt_format);
if (format < 0)
goto err;
EC_GROUP_set_point_conversion_form(gctx->gen_group, format);
}
}
/* We must always assign a group, no matter what */
ret = ec_gen_assign_group(ec, gctx->gen_group);
/* Whether you want it or not, you get a keypair, not just one half */
if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
ret = ret && EC_KEY_generate_key(ec);
if (gctx->ecdh_mode != -1)
ret = ret && ossl_ec_set_ecdh_cofactor_mode(ec, gctx->ecdh_mode);
if (gctx->group_check != NULL)
ret = ret && ossl_ec_set_check_group_type_from_name(ec, gctx->group_check);
if (ret)
return ec;
err:
/* Something went wrong, throw the key away */
EC_KEY_free(ec);
return NULL;
}
#ifndef FIPS_MODULE
# ifndef OPENSSL_NO_SM2
/*
* The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
*/
static void *sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
{
struct ec_gen_ctx *gctx = genctx;
EC_KEY *ec = NULL;
int ret = 1;
if (gctx == NULL
|| (ec = EC_KEY_new_ex(gctx->libctx, NULL)) == NULL)
return NULL;
if (gctx->gen_group == NULL) {
if (!ec_gen_set_group_from_params(gctx))
goto err;
} else {
if (gctx->encoding) {
int flags = ossl_ec_encoding_name2id(gctx->encoding);
if (flags < 0)
goto err;
EC_GROUP_set_asn1_flag(gctx->gen_group, flags);
}
if (gctx->pt_format != NULL) {
int format = ossl_ec_pt_format_name2id(gctx->pt_format);
if (format < 0)
goto err;
EC_GROUP_set_point_conversion_form(gctx->gen_group, format);
}
}
/* We must always assign a group, no matter what */
ret = ec_gen_assign_group(ec, gctx->gen_group);
/* Whether you want it or not, you get a keypair, not just one half */
if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
ret = ret && EC_KEY_generate_key(ec);
if (ret)
return ec;
err:
/* Something went wrong, throw the key away */
EC_KEY_free(ec);
return NULL;
}
# endif
#endif
static void ec_gen_cleanup(void *genctx)
{
struct ec_gen_ctx *gctx = genctx;
if (gctx == NULL)
return;
EC_GROUP_free(gctx->gen_group);
BN_free(gctx->p);
BN_free(gctx->a);
BN_free(gctx->b);
BN_free(gctx->order);
BN_free(gctx->cofactor);
OPENSSL_free(gctx->group_name);
OPENSSL_free(gctx->field_type);
OPENSSL_free(gctx->pt_format);
OPENSSL_free(gctx->encoding);
OPENSSL_free(gctx->seed);
OPENSSL_free(gctx->gen);
OPENSSL_free(gctx);
}
static void *common_load(const void *reference, size_t reference_sz,
int sm2_wanted)
{
EC_KEY *ec = NULL;
if (ossl_prov_is_running() && reference_sz == sizeof(ec)) {
/* The contents of the reference is the address to our object */
ec = *(EC_KEY **)reference;
if (!common_check_sm2(ec, sm2_wanted))
return NULL;
/* We grabbed, so we detach it */
*(EC_KEY **)reference = NULL;
return ec;
}
return NULL;
}
static void *ec_load(const void *reference, size_t reference_sz)
{
return common_load(reference, reference_sz, 0);
}
#ifndef FIPS_MODULE
# ifndef OPENSSL_NO_SM2
static void *sm2_load(const void *reference, size_t reference_sz)
{
return common_load(reference, reference_sz, 1);
}
# endif
#endif
static void *ec_dup(const void *keydata_from, int selection)
{
if (ossl_prov_is_running())
return ossl_ec_key_dup(keydata_from, selection);
return NULL;
}
const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init },
{ OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
(void (*)(void))ec_gen_set_template },
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
(void (*)(void))ec_gen_settable_params },
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ec_gen },
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ec_load },
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ec_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ec_gettable_params },
{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ec_settable_params },
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ec_validate },
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ec_import },
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
{ OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
(void (*)(void))ec_query_operation_name },
{ OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },
{ 0, NULL }
};
#ifndef FIPS_MODULE
# ifndef OPENSSL_NO_SM2
const OSSL_DISPATCH ossl_sm2_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))sm2_newdata },
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))sm2_gen_init },
{ OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
(void (*)(void))ec_gen_set_template },
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
(void (*)(void))ec_gen_settable_params },
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))sm2_gen },
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))sm2_load },
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))sm2_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))sm2_gettable_params },
{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))sm2_settable_params },
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))sm2_validate },
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sm2_import },
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
{ OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
(void (*)(void))sm2_query_operation_name },
{ OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },
{ 0, NULL }
};
# endif
#endif
diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c
index b76835ccc437..3ba12c4889a8 100644
--- a/providers/implementations/keymgmt/rsa_kmgmt.c
+++ b/providers/implementations/keymgmt/rsa_kmgmt.c
@@ -1,744 +1,744 @@
/*
- * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/*
* RSA 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 <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/proverr.h>
#include "prov/implementations.h"
#include "prov/providercommon.h"
#include "prov/provider_ctx.h"
#include "crypto/rsa.h"
#include "crypto/cryptlib.h"
#include "internal/param_build_set.h"
static OSSL_FUNC_keymgmt_new_fn rsa_newdata;
static OSSL_FUNC_keymgmt_new_fn rsapss_newdata;
static OSSL_FUNC_keymgmt_gen_init_fn rsa_gen_init;
static OSSL_FUNC_keymgmt_gen_init_fn rsapss_gen_init;
static OSSL_FUNC_keymgmt_gen_set_params_fn rsa_gen_set_params;
static OSSL_FUNC_keymgmt_gen_settable_params_fn rsa_gen_settable_params;
static OSSL_FUNC_keymgmt_gen_settable_params_fn rsapss_gen_settable_params;
static OSSL_FUNC_keymgmt_gen_fn rsa_gen;
static OSSL_FUNC_keymgmt_gen_cleanup_fn rsa_gen_cleanup;
static OSSL_FUNC_keymgmt_load_fn rsa_load;
static OSSL_FUNC_keymgmt_load_fn rsapss_load;
static OSSL_FUNC_keymgmt_free_fn rsa_freedata;
static OSSL_FUNC_keymgmt_get_params_fn rsa_get_params;
static OSSL_FUNC_keymgmt_gettable_params_fn rsa_gettable_params;
static OSSL_FUNC_keymgmt_has_fn rsa_has;
static OSSL_FUNC_keymgmt_match_fn rsa_match;
static OSSL_FUNC_keymgmt_validate_fn rsa_validate;
static OSSL_FUNC_keymgmt_import_fn rsa_import;
static OSSL_FUNC_keymgmt_import_types_fn rsa_import_types;
static OSSL_FUNC_keymgmt_export_fn rsa_export;
static OSSL_FUNC_keymgmt_export_types_fn rsa_export_types;
static OSSL_FUNC_keymgmt_query_operation_name_fn rsa_query_operation_name;
static OSSL_FUNC_keymgmt_dup_fn rsa_dup;
#define RSA_DEFAULT_MD "SHA256"
#define RSA_PSS_DEFAULT_MD OSSL_DIGEST_NAME_SHA1
#define RSA_POSSIBLE_SELECTIONS \
(OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS)
DEFINE_STACK_OF(BIGNUM)
DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
static int pss_params_fromdata(RSA_PSS_PARAMS_30 *pss_params, int *defaults_set,
const OSSL_PARAM params[], int rsa_type,
OSSL_LIB_CTX *libctx)
{
if (!ossl_rsa_pss_params_30_fromdata(pss_params, defaults_set,
params, libctx))
return 0;
/* If not a PSS type RSA, sending us PSS parameters is wrong */
if (rsa_type != RSA_FLAG_TYPE_RSASSAPSS
&& !ossl_rsa_pss_params_30_is_unrestricted(pss_params))
return 0;
return 1;
}
static void *rsa_newdata(void *provctx)
{
OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
RSA *rsa;
if (!ossl_prov_is_running())
return NULL;
rsa = ossl_rsa_new_with_ctx(libctx);
if (rsa != NULL) {
RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK);
RSA_set_flags(rsa, RSA_FLAG_TYPE_RSA);
}
return rsa;
}
static void *rsapss_newdata(void *provctx)
{
OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
RSA *rsa;
if (!ossl_prov_is_running())
return NULL;
rsa = ossl_rsa_new_with_ctx(libctx);
if (rsa != NULL) {
RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK);
RSA_set_flags(rsa, RSA_FLAG_TYPE_RSASSAPSS);
}
return rsa;
}
static void rsa_freedata(void *keydata)
{
RSA_free(keydata);
}
static int rsa_has(const void *keydata, int selection)
{
const RSA *rsa = keydata;
int ok = 1;
if (rsa == NULL || !ossl_prov_is_running())
return 0;
if ((selection & RSA_POSSIBLE_SELECTIONS) == 0)
return 1; /* the selection is not missing */
/* OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS are always available even if empty */
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
- ok = ok && (RSA_get0_e(rsa) != NULL);
- if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
ok = ok && (RSA_get0_n(rsa) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && (RSA_get0_e(rsa) != NULL);
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = ok && (RSA_get0_d(rsa) != NULL);
return ok;
}
static int rsa_match(const void *keydata1, const void *keydata2, int selection)
{
const RSA *rsa1 = keydata1;
const RSA *rsa2 = keydata2;
int ok = 1;
if (!ossl_prov_is_running())
return 0;
/* There is always an |e| */
ok = ok && BN_cmp(RSA_get0_e(rsa1), RSA_get0_e(rsa2)) == 0;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
int key_checked = 0;
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
const BIGNUM *pa = RSA_get0_n(rsa1);
const BIGNUM *pb = RSA_get0_n(rsa2);
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 = RSA_get0_d(rsa1);
const BIGNUM *pb = RSA_get0_d(rsa2);
if (pa != NULL && pb != NULL) {
ok = ok && BN_cmp(pa, pb) == 0;
key_checked = 1;
}
}
ok = ok && key_checked;
}
return ok;
}
static int rsa_import(void *keydata, int selection, const OSSL_PARAM params[])
{
RSA *rsa = keydata;
int rsa_type;
int ok = 1;
int pss_defaults_set = 0;
if (!ossl_prov_is_running() || rsa == NULL)
return 0;
if ((selection & RSA_POSSIBLE_SELECTIONS) == 0)
return 0;
rsa_type = RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK);
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
ok = ok && pss_params_fromdata(ossl_rsa_get0_pss_params_30(rsa),
&pss_defaults_set,
params, rsa_type,
ossl_rsa_get0_libctx(rsa));
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
int include_private =
selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
ok = ok && ossl_rsa_fromdata(rsa, params, include_private);
}
return ok;
}
static int rsa_export(void *keydata, int selection,
OSSL_CALLBACK *param_callback, void *cbarg)
{
RSA *rsa = keydata;
const RSA_PSS_PARAMS_30 *pss_params = ossl_rsa_get0_pss_params_30(rsa);
OSSL_PARAM_BLD *tmpl;
OSSL_PARAM *params = NULL;
int ok = 1;
if (!ossl_prov_is_running() || rsa == NULL)
return 0;
if ((selection & RSA_POSSIBLE_SELECTIONS) == 0)
return 0;
tmpl = OSSL_PARAM_BLD_new();
if (tmpl == NULL)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
ok = ok && (ossl_rsa_pss_params_30_is_unrestricted(pss_params)
|| ossl_rsa_pss_params_30_todata(pss_params, tmpl, NULL));
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
int include_private =
selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
ok = ok && ossl_rsa_todata(rsa, tmpl, NULL, include_private);
}
if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
ok = 0;
goto err;
}
ok = param_callback(params, cbarg);
OSSL_PARAM_free(params);
err:
OSSL_PARAM_BLD_free(tmpl);
return ok;
}
#ifdef FIPS_MODULE
/* In fips mode there are no multi-primes. */
# define RSA_KEY_MP_TYPES() \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR1, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR2, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT1, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT2, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, NULL, 0),
#else
/*
* We allow up to 10 prime factors (starting with p, q).
* NOTE: there is only 9 OSSL_PKEY_PARAM_RSA_COEFFICIENT
*/
# define RSA_KEY_MP_TYPES() \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR1, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR2, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR3, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR4, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR5, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR6, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR7, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR8, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR9, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR10, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT1, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT2, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT3, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT4, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT5, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT6, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT7, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT8, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT9, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT10, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT2, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT3, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT4, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT5, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT6, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT7, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT8, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT9, NULL, 0),
#endif
#define RSA_KEY_TYPES() \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_D, NULL, 0), \
RSA_KEY_MP_TYPES()
/*
* This provider can export everything in an RSA key, so we use the exact
* same type description for export as for import. Other providers might
* choose to import full keys, but only export the public parts, and will
* therefore have the importkey_types and importkey_types functions return
* different arrays.
*/
static const OSSL_PARAM rsa_key_types[] = {
RSA_KEY_TYPES()
OSSL_PARAM_END
};
/*
* We lied about the amount of factors, exponents and coefficients, the
* export and import functions can really deal with an infinite amount
* of these numbers. However, RSA keys with too many primes are futile,
* so we at least pretend to have some limits.
*/
static const OSSL_PARAM *rsa_imexport_types(int selection)
{
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
return rsa_key_types;
return NULL;
}
static const OSSL_PARAM *rsa_import_types(int selection)
{
return rsa_imexport_types(selection);
}
static const OSSL_PARAM *rsa_export_types(int selection)
{
return rsa_imexport_types(selection);
}
static int rsa_get_params(void *key, OSSL_PARAM params[])
{
RSA *rsa = key;
const RSA_PSS_PARAMS_30 *pss_params = ossl_rsa_get0_pss_params_30(rsa);
int rsa_type = RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK);
OSSL_PARAM *p;
int empty = RSA_get0_n(rsa) == NULL;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
&& (empty || !OSSL_PARAM_set_int(p, RSA_bits(rsa))))
return 0;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
&& (empty || !OSSL_PARAM_set_int(p, RSA_security_bits(rsa))))
return 0;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
&& (empty || !OSSL_PARAM_set_int(p, RSA_size(rsa))))
return 0;
/*
* For restricted RSA-PSS keys, we ignore the default digest request.
* With RSA-OAEP keys, this may need to be amended.
*/
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
&& (rsa_type != RSA_FLAG_TYPE_RSASSAPSS
|| ossl_rsa_pss_params_30_is_unrestricted(pss_params))) {
if (!OSSL_PARAM_set_utf8_string(p, RSA_DEFAULT_MD))
return 0;
}
/*
* For non-RSA-PSS keys, we ignore the mandatory digest request.
* With RSA-OAEP keys, this may need to be amended.
*/
if ((p = OSSL_PARAM_locate(params,
OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
&& rsa_type == RSA_FLAG_TYPE_RSASSAPSS
&& !ossl_rsa_pss_params_30_is_unrestricted(pss_params)) {
const char *mdname =
ossl_rsa_oaeppss_nid2name(ossl_rsa_pss_params_30_hashalg(pss_params));
if (mdname == NULL || !OSSL_PARAM_set_utf8_string(p, mdname))
return 0;
}
return (rsa_type != RSA_FLAG_TYPE_RSASSAPSS
|| ossl_rsa_pss_params_30_todata(pss_params, NULL, params))
&& ossl_rsa_todata(rsa, NULL, params, 1);
}
static const OSSL_PARAM rsa_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),
RSA_KEY_TYPES()
OSSL_PARAM_END
};
static const OSSL_PARAM *rsa_gettable_params(void *provctx)
{
return rsa_params;
}
static int rsa_validate(const void *keydata, int selection, int checktype)
{
const RSA *rsa = keydata;
int ok = 1;
if (!ossl_prov_is_running())
return 0;
if ((selection & RSA_POSSIBLE_SELECTIONS) == 0)
return 1; /* nothing to validate */
/* If the whole key is selected, we do a pairwise validation */
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)
== OSSL_KEYMGMT_SELECT_KEYPAIR) {
ok = ok && ossl_rsa_validate_pairwise(rsa);
} else {
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = ok && ossl_rsa_validate_private(rsa);
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
ok = ok && ossl_rsa_validate_public(rsa);
}
return ok;
}
struct rsa_gen_ctx {
OSSL_LIB_CTX *libctx;
const char *propq;
int rsa_type;
size_t nbits;
BIGNUM *pub_exp;
size_t primes;
/* For PSS */
RSA_PSS_PARAMS_30 pss_params;
int pss_defaults_set;
/* For generation callback */
OSSL_CALLBACK *cb;
void *cbarg;
#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
/* ACVP test parameters */
OSSL_PARAM *acvp_test_params;
#endif
};
static int rsa_gencb(int p, int n, BN_GENCB *cb)
{
struct rsa_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 *gen_init(void *provctx, int selection, int rsa_type,
const OSSL_PARAM params[])
{
OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
struct rsa_gen_ctx *gctx = NULL;
if (!ossl_prov_is_running())
return NULL;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
return NULL;
if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
gctx->libctx = libctx;
if ((gctx->pub_exp = BN_new()) == NULL
|| !BN_set_word(gctx->pub_exp, RSA_F4)) {
goto err;
}
gctx->nbits = 2048;
gctx->primes = RSA_DEFAULT_PRIME_NUM;
gctx->rsa_type = rsa_type;
} else {
goto err;
}
if (!rsa_gen_set_params(gctx, params))
goto err;
return gctx;
err:
if (gctx != NULL)
BN_free(gctx->pub_exp);
OPENSSL_free(gctx);
return NULL;
}
static void *rsa_gen_init(void *provctx, int selection,
const OSSL_PARAM params[])
{
return gen_init(provctx, selection, RSA_FLAG_TYPE_RSA, params);
}
static void *rsapss_gen_init(void *provctx, int selection,
const OSSL_PARAM params[])
{
return gen_init(provctx, selection, RSA_FLAG_TYPE_RSASSAPSS, params);
}
/*
* This function is common for all RSA sub-types, to detect possible
* misuse, such as PSS parameters being passed when a plain RSA key
* is generated.
*/
static int rsa_gen_set_params(void *genctx, const OSSL_PARAM params[])
{
struct rsa_gen_ctx *gctx = genctx;
const OSSL_PARAM *p;
if (params == NULL)
return 1;
if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_BITS)) != NULL) {
if (!OSSL_PARAM_get_size_t(p, &gctx->nbits))
return 0;
if (gctx->nbits < RSA_MIN_MODULUS_BITS) {
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL);
return 0;
}
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_PRIMES)) != NULL
&& !OSSL_PARAM_get_size_t(p, &gctx->primes))
return 0;
if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E)) != NULL
&& !OSSL_PARAM_get_BN(p, &gctx->pub_exp))
return 0;
/* Only attempt to get PSS parameters when generating an RSA-PSS key */
if (gctx->rsa_type == RSA_FLAG_TYPE_RSASSAPSS
&& !pss_params_fromdata(&gctx->pss_params, &gctx->pss_defaults_set, params,
gctx->rsa_type, gctx->libctx))
return 0;
#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
/* Any ACVP test related parameters are copied into a params[] */
if (!ossl_rsa_acvp_test_gen_params_new(&gctx->acvp_test_params, params))
return 0;
#endif
return 1;
}
#define rsa_gen_basic \
OSSL_PARAM_size_t(OSSL_PKEY_PARAM_RSA_BITS, NULL), \
OSSL_PARAM_size_t(OSSL_PKEY_PARAM_RSA_PRIMES, NULL), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0)
/*
* The following must be kept in sync with ossl_rsa_pss_params_30_fromdata()
* in crypto/rsa/rsa_backend.c
*/
#define rsa_gen_pss \
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST, NULL, 0), \
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST_PROPS, NULL, 0), \
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MASKGENFUNC, NULL, 0), \
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MGF1_DIGEST, NULL, 0), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_RSA_PSS_SALTLEN, NULL)
static const OSSL_PARAM *rsa_gen_settable_params(ossl_unused void *genctx,
ossl_unused void *provctx)
{
static OSSL_PARAM settable[] = {
rsa_gen_basic,
OSSL_PARAM_END
};
return settable;
}
static const OSSL_PARAM *rsapss_gen_settable_params(ossl_unused void *genctx,
ossl_unused void *provctx)
{
static OSSL_PARAM settable[] = {
rsa_gen_basic,
rsa_gen_pss,
OSSL_PARAM_END
};
return settable;
}
static void *rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
{
struct rsa_gen_ctx *gctx = genctx;
RSA *rsa = NULL, *rsa_tmp = NULL;
BN_GENCB *gencb = NULL;
if (!ossl_prov_is_running() || gctx == NULL)
return NULL;
switch (gctx->rsa_type) {
case RSA_FLAG_TYPE_RSA:
/* For plain RSA keys, PSS parameters must not be set */
if (!ossl_rsa_pss_params_30_is_unrestricted(&gctx->pss_params))
goto err;
break;
case RSA_FLAG_TYPE_RSASSAPSS:
/*
* For plain RSA-PSS keys, PSS parameters may be set but don't have
* to, so not check.
*/
break;
default:
/* Unsupported RSA key sub-type... */
return NULL;
}
if ((rsa_tmp = ossl_rsa_new_with_ctx(gctx->libctx)) == NULL)
return NULL;
gctx->cb = osslcb;
gctx->cbarg = cbarg;
gencb = BN_GENCB_new();
if (gencb != NULL)
BN_GENCB_set(gencb, rsa_gencb, genctx);
#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
if (gctx->acvp_test_params != NULL) {
if (!ossl_rsa_acvp_test_set_params(rsa_tmp, gctx->acvp_test_params))
goto err;
}
#endif
if (!RSA_generate_multi_prime_key(rsa_tmp,
(int)gctx->nbits, (int)gctx->primes,
gctx->pub_exp, gencb))
goto err;
if (!ossl_rsa_pss_params_30_copy(ossl_rsa_get0_pss_params_30(rsa_tmp),
&gctx->pss_params))
goto err;
RSA_clear_flags(rsa_tmp, RSA_FLAG_TYPE_MASK);
RSA_set_flags(rsa_tmp, gctx->rsa_type);
rsa = rsa_tmp;
rsa_tmp = NULL;
err:
BN_GENCB_free(gencb);
RSA_free(rsa_tmp);
return rsa;
}
static void rsa_gen_cleanup(void *genctx)
{
struct rsa_gen_ctx *gctx = genctx;
if (gctx == NULL)
return;
#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
ossl_rsa_acvp_test_gen_params_free(gctx->acvp_test_params);
gctx->acvp_test_params = NULL;
#endif
BN_clear_free(gctx->pub_exp);
OPENSSL_free(gctx);
}
static void *common_load(const void *reference, size_t reference_sz,
int expected_rsa_type)
{
RSA *rsa = NULL;
if (ossl_prov_is_running() && reference_sz == sizeof(rsa)) {
/* The contents of the reference is the address to our object */
rsa = *(RSA **)reference;
if (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK) != expected_rsa_type)
return NULL;
/* We grabbed, so we detach it */
*(RSA **)reference = NULL;
return rsa;
}
return NULL;
}
static void *rsa_load(const void *reference, size_t reference_sz)
{
return common_load(reference, reference_sz, RSA_FLAG_TYPE_RSA);
}
static void *rsapss_load(const void *reference, size_t reference_sz)
{
return common_load(reference, reference_sz, RSA_FLAG_TYPE_RSASSAPSS);
}
static void *rsa_dup(const void *keydata_from, int selection)
{
if (ossl_prov_is_running()
/* do not allow creating empty keys by duplication */
&& (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
return ossl_rsa_dup(keydata_from, selection);
return NULL;
}
/* For any RSA key, we use the "RSA" algorithms regardless of sub-type. */
static const char *rsa_query_operation_name(int operation_id)
{
return "RSA";
}
const OSSL_DISPATCH ossl_rsa_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))rsa_newdata },
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))rsa_gen_init },
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS,
(void (*)(void))rsa_gen_set_params },
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
(void (*)(void))rsa_gen_settable_params },
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))rsa_gen },
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))rsa_gen_cleanup },
{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))rsa_load },
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))rsa_freedata },
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))rsa_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))rsa_gettable_params },
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))rsa_has },
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))rsa_match },
{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))rsa_validate },
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))rsa_import },
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))rsa_import_types },
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))rsa_export },
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))rsa_export_types },
{ OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))rsa_dup },
{ 0, NULL }
};
const OSSL_DISPATCH ossl_rsapss_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))rsapss_newdata },
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))rsapss_gen_init },
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))rsa_gen_set_params },
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
(void (*)(void))rsapss_gen_settable_params },
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))rsa_gen },
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))rsa_gen_cleanup },
{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))rsapss_load },
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))rsa_freedata },
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))rsa_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))rsa_gettable_params },
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))rsa_has },
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))rsa_match },
{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))rsa_validate },
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))rsa_import },
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))rsa_import_types },
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))rsa_export },
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))rsa_export_types },
{ OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
(void (*)(void))rsa_query_operation_name },
{ OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))rsa_dup },
{ 0, NULL }
};
diff --git a/providers/implementations/rands/drbg.c b/providers/implementations/rands/drbg.c
index c8fe66aa573f..e30836c53cab 100644
--- a/providers/implementations/rands/drbg.c
+++ b/providers/implementations/rands/drbg.c
@@ -1,934 +1,934 @@
/*
- * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-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/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include "crypto/rand.h"
#include <openssl/proverr.h>
#include "drbg_local.h"
#include "internal/thread_once.h"
#include "crypto/cryptlib.h"
#include "prov/seeding.h"
#include "crypto/rand_pool.h"
#include "prov/provider_ctx.h"
#include "prov/providercommon.h"
/*
* Support framework for NIST SP 800-90A DRBG
*
* See manual page PROV_DRBG(7) for a general overview.
*
* The OpenSSL model is to have new and free functions, and that new
* does all initialization. That is not the NIST model, which has
* instantiation and un-instantiate, and re-use within a new/free
* lifecycle. (No doubt this comes from the desire to support hardware
* DRBG, where allocation of resources on something like an HSM is
* a much bigger deal than just re-setting an allocated resource.)
*/
/* NIST SP 800-90A DRBG recommends the use of a personalization string. */
static const char ossl_pers_string[] = DRBG_DEFAULT_PERS_STRING;
static const OSSL_DISPATCH *find_call(const OSSL_DISPATCH *dispatch,
int function);
static int rand_drbg_restart(PROV_DRBG *drbg);
int ossl_drbg_lock(void *vctx)
{
PROV_DRBG *drbg = vctx;
if (drbg == NULL || drbg->lock == NULL)
return 1;
return CRYPTO_THREAD_write_lock(drbg->lock);
}
void ossl_drbg_unlock(void *vctx)
{
PROV_DRBG *drbg = vctx;
if (drbg != NULL && drbg->lock != NULL)
CRYPTO_THREAD_unlock(drbg->lock);
}
static int ossl_drbg_lock_parent(PROV_DRBG *drbg)
{
void *parent = drbg->parent;
if (parent != NULL
&& drbg->parent_lock != NULL
&& !drbg->parent_lock(parent)) {
ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED);
return 0;
}
return 1;
}
static void ossl_drbg_unlock_parent(PROV_DRBG *drbg)
{
void *parent = drbg->parent;
if (parent != NULL && drbg->parent_unlock != NULL)
drbg->parent_unlock(parent);
}
static int get_parent_strength(PROV_DRBG *drbg, unsigned int *str)
{
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
void *parent = drbg->parent;
int res;
if (drbg->parent_get_ctx_params == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH);
return 0;
}
*params = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, str);
if (!ossl_drbg_lock_parent(drbg)) {
ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOCK_PARENT);
return 0;
}
res = drbg->parent_get_ctx_params(parent, params);
ossl_drbg_unlock_parent(drbg);
if (!res) {
ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH);
return 0;
}
return 1;
}
static unsigned int get_parent_reseed_count(PROV_DRBG *drbg)
{
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
void *parent = drbg->parent;
unsigned int r = 0;
*params = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_COUNTER, &r);
if (!ossl_drbg_lock_parent(drbg)) {
ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOCK_PARENT);
goto err;
}
if (!drbg->parent_get_ctx_params(parent, params))
r = 0;
ossl_drbg_unlock_parent(drbg);
return r;
err:
r = tsan_load(&drbg->reseed_counter) - 2;
if (r == 0)
r = UINT_MAX;
return r;
}
/*
* Implements the get_entropy() callback
*
* If the DRBG has a parent, then the required amount of entropy input
* is fetched using the parent's ossl_prov_drbg_generate().
*
* Otherwise, the entropy is polled from the system entropy sources
* using ossl_pool_acquire_entropy().
*
* If a random pool has been added to the DRBG using RAND_add(), then
* its entropy will be used up first.
*/
size_t ossl_drbg_get_seed(void *vdrbg, unsigned char **pout,
int entropy, size_t min_len,
size_t max_len, int prediction_resistance,
const unsigned char *adin, size_t adin_len)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
size_t bytes_needed;
unsigned char *buffer;
/* Figure out how many bytes we need */
bytes_needed = entropy >= 0 ? (entropy + 7) / 8 : 0;
if (bytes_needed < min_len)
bytes_needed = min_len;
if (bytes_needed > max_len)
bytes_needed = max_len;
/* Allocate storage */
buffer = OPENSSL_secure_malloc(bytes_needed);
if (buffer == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
/*
* Get random data. Include our DRBG address as
* additional input, in order to provide a distinction between
* different DRBG child instances.
*
* Note: using the sizeof() operator on a pointer triggers
* a warning in some static code analyzers, but it's
* intentional and correct here.
*/
if (!ossl_prov_drbg_generate(drbg, buffer, bytes_needed,
drbg->strength, prediction_resistance,
(unsigned char *)&drbg, sizeof(drbg))) {
OPENSSL_secure_clear_free(buffer, bytes_needed);
ERR_raise(ERR_LIB_PROV, PROV_R_GENERATE_ERROR);
return 0;
}
*pout = buffer;
return bytes_needed;
}
/* Implements the cleanup_entropy() callback */
void ossl_drbg_clear_seed(ossl_unused void *vdrbg,
unsigned char *out, size_t outlen)
{
OPENSSL_secure_clear_free(out, outlen);
}
static size_t get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy,
size_t min_len, size_t max_len,
int prediction_resistance)
{
size_t bytes;
unsigned int p_str;
if (drbg->parent == NULL)
#ifdef FIPS_MODULE
return ossl_crngt_get_entropy(drbg, pout, entropy, min_len, max_len,
prediction_resistance);
#else
return ossl_prov_get_entropy(drbg->provctx, pout, entropy, min_len,
max_len);
#endif
if (drbg->parent_get_seed == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED);
return 0;
}
if (!get_parent_strength(drbg, &p_str))
return 0;
if (drbg->strength > p_str) {
/*
* We currently don't support the algorithm from NIST SP 800-90C
* 10.1.2 to use a weaker DRBG as source
*/
ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK);
return 0;
}
/*
* Our lock is already held, but we need to lock our parent before
* generating bits from it. Note: taking the lock will be a no-op
* if locking is not required (while drbg->parent->lock == NULL).
*/
if (!ossl_drbg_lock_parent(drbg))
return 0;
/*
* Get random data from parent. Include our DRBG address as
* additional input, in order to provide a distinction between
* different DRBG child instances.
*
* Note: using the sizeof() operator on a pointer triggers
* a warning in some static code analyzers, but it's
* intentional and correct here.
*/
bytes = drbg->parent_get_seed(drbg->parent, pout, drbg->strength,
min_len, max_len, prediction_resistance,
(unsigned char *)&drbg, sizeof(drbg));
ossl_drbg_unlock_parent(drbg);
return bytes;
}
static void cleanup_entropy(PROV_DRBG *drbg, unsigned char *out, size_t outlen)
{
if (drbg->parent == NULL) {
#ifdef FIPS_MODULE
ossl_crngt_cleanup_entropy(drbg, out, outlen);
#else
ossl_prov_cleanup_entropy(drbg->provctx, out, outlen);
#endif
} else if (drbg->parent_clear_seed != NULL) {
if (!ossl_drbg_lock_parent(drbg))
return;
- drbg->parent_clear_seed(drbg, out, outlen);
+ drbg->parent_clear_seed(drbg->parent, out, outlen);
ossl_drbg_unlock_parent(drbg);
}
}
#ifndef PROV_RAND_GET_RANDOM_NONCE
typedef struct prov_drbg_nonce_global_st {
CRYPTO_RWLOCK *rand_nonce_lock;
int rand_nonce_count;
} PROV_DRBG_NONCE_GLOBAL;
/*
* drbg_ossl_ctx_new() calls drgb_setup() which calls rand_drbg_get_nonce()
* which needs to get the rand_nonce_lock out of the OSSL_LIB_CTX...but since
* drbg_ossl_ctx_new() hasn't finished running yet we need the rand_nonce_lock
* to be in a different global data object. Otherwise we will go into an
* infinite recursion loop.
*/
static void *prov_drbg_nonce_ossl_ctx_new(OSSL_LIB_CTX *libctx)
{
PROV_DRBG_NONCE_GLOBAL *dngbl = OPENSSL_zalloc(sizeof(*dngbl));
if (dngbl == NULL)
return NULL;
dngbl->rand_nonce_lock = CRYPTO_THREAD_lock_new();
if (dngbl->rand_nonce_lock == NULL) {
OPENSSL_free(dngbl);
return NULL;
}
return dngbl;
}
static void prov_drbg_nonce_ossl_ctx_free(void *vdngbl)
{
PROV_DRBG_NONCE_GLOBAL *dngbl = vdngbl;
if (dngbl == NULL)
return;
CRYPTO_THREAD_lock_free(dngbl->rand_nonce_lock);
OPENSSL_free(dngbl);
}
static const OSSL_LIB_CTX_METHOD drbg_nonce_ossl_ctx_method = {
OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
prov_drbg_nonce_ossl_ctx_new,
prov_drbg_nonce_ossl_ctx_free,
};
/* Get a nonce from the operating system */
static size_t prov_drbg_get_nonce(PROV_DRBG *drbg, unsigned char **pout,
size_t min_len, size_t max_len)
{
size_t ret = 0, n;
unsigned char *buf = NULL;
OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx);
PROV_DRBG_NONCE_GLOBAL *dngbl
= ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_NONCE_INDEX,
&drbg_nonce_ossl_ctx_method);
struct {
void *drbg;
int count;
} data;
if (dngbl == NULL)
return 0;
if (drbg->parent != NULL && drbg->parent_nonce != NULL) {
n = drbg->parent_nonce(drbg->parent, NULL, 0, drbg->min_noncelen,
drbg->max_noncelen);
if (n > 0 && (buf = OPENSSL_malloc(n)) != NULL) {
ret = drbg->parent_nonce(drbg->parent, buf, 0,
drbg->min_noncelen, drbg->max_noncelen);
if (ret == n) {
*pout = buf;
return ret;
}
OPENSSL_free(buf);
}
}
/* Use the built in nonce source plus some of our specifics */
memset(&data, 0, sizeof(data));
data.drbg = drbg;
CRYPTO_atomic_add(&dngbl->rand_nonce_count, 1, &data.count,
dngbl->rand_nonce_lock);
return ossl_prov_get_nonce(drbg->provctx, pout, min_len, max_len,
&data, sizeof(data));
}
#endif /* PROV_RAND_GET_RANDOM_NONCE */
/*
* Instantiate |drbg|, after it has been initialized. Use |pers| and
* |perslen| as prediction-resistance input.
*
* Requires that drbg->lock is already locked for write, if non-null.
*
* Returns 1 on success, 0 on failure.
*/
int ossl_prov_drbg_instantiate(PROV_DRBG *drbg, unsigned int strength,
int prediction_resistance,
const unsigned char *pers, size_t perslen)
{
unsigned char *nonce = NULL, *entropy = NULL;
size_t noncelen = 0, entropylen = 0;
size_t min_entropy, min_entropylen, max_entropylen;
if (strength > drbg->strength) {
ERR_raise(ERR_LIB_PROV, PROV_R_INSUFFICIENT_DRBG_STRENGTH);
goto end;
}
min_entropy = drbg->strength;
min_entropylen = drbg->min_entropylen;
max_entropylen = drbg->max_entropylen;
if (pers == NULL) {
pers = (const unsigned char *)ossl_pers_string;
perslen = sizeof(ossl_pers_string);
}
if (perslen > drbg->max_perslen) {
ERR_raise(ERR_LIB_PROV, PROV_R_PERSONALISATION_STRING_TOO_LONG);
goto end;
}
if (drbg->state != EVP_RAND_STATE_UNINITIALISED) {
if (drbg->state == EVP_RAND_STATE_ERROR)
ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);
else
ERR_raise(ERR_LIB_PROV, PROV_R_ALREADY_INSTANTIATED);
goto end;
}
drbg->state = EVP_RAND_STATE_ERROR;
if (drbg->min_noncelen > 0) {
if (drbg->parent_nonce != NULL) {
noncelen = drbg->parent_nonce(drbg->parent, NULL, drbg->strength,
drbg->min_noncelen,
drbg->max_noncelen);
if (noncelen == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
goto end;
}
nonce = OPENSSL_malloc(noncelen);
if (nonce == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
goto end;
}
if (noncelen != drbg->parent_nonce(drbg->parent, nonce,
drbg->strength,
drbg->min_noncelen,
drbg->max_noncelen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
goto end;
}
#ifndef PROV_RAND_GET_RANDOM_NONCE
} else if (drbg->parent != NULL) {
#endif
/*
* NIST SP800-90Ar1 section 9.1 says you can combine getting
* the entropy and nonce in 1 call by increasing the entropy
* with 50% and increasing the minimum length to accommodate
* the length of the nonce. We do this in case a nonce is
* required and there is no parental nonce capability.
*/
min_entropy += drbg->strength / 2;
min_entropylen += drbg->min_noncelen;
max_entropylen += drbg->max_noncelen;
}
#ifndef PROV_RAND_GET_RANDOM_NONCE
else { /* parent == NULL */
noncelen = prov_drbg_get_nonce(drbg, &nonce, drbg->min_noncelen,
drbg->max_noncelen);
if (noncelen < drbg->min_noncelen
|| noncelen > drbg->max_noncelen) {
ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
goto end;
}
}
#endif
}
drbg->reseed_next_counter = tsan_load(&drbg->reseed_counter);
if (drbg->reseed_next_counter) {
drbg->reseed_next_counter++;
if (!drbg->reseed_next_counter)
drbg->reseed_next_counter = 1;
}
entropylen = get_entropy(drbg, &entropy, min_entropy,
min_entropylen, max_entropylen,
prediction_resistance);
if (entropylen < min_entropylen
|| entropylen > max_entropylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY);
goto end;
}
if (!drbg->instantiate(drbg, entropy, entropylen, nonce, noncelen,
pers, perslen)) {
cleanup_entropy(drbg, entropy, entropylen);
ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_INSTANTIATING_DRBG);
goto end;
}
cleanup_entropy(drbg, entropy, entropylen);
drbg->state = EVP_RAND_STATE_READY;
drbg->generate_counter = 1;
drbg->reseed_time = time(NULL);
tsan_store(&drbg->reseed_counter, drbg->reseed_next_counter);
end:
if (nonce != NULL)
ossl_prov_cleanup_nonce(drbg->provctx, nonce, noncelen);
if (drbg->state == EVP_RAND_STATE_READY)
return 1;
return 0;
}
/*
* Uninstantiate |drbg|. Must be instantiated before it can be used.
*
* Requires that drbg->lock is already locked for write, if non-null.
*
* Returns 1 on success, 0 on failure.
*/
int ossl_prov_drbg_uninstantiate(PROV_DRBG *drbg)
{
drbg->state = EVP_RAND_STATE_UNINITIALISED;
return 1;
}
/*
* Reseed |drbg|, mixing in the specified data
*
* Requires that drbg->lock is already locked for write, if non-null.
*
* Returns 1 on success, 0 on failure.
*/
int ossl_prov_drbg_reseed(PROV_DRBG *drbg, int prediction_resistance,
const unsigned char *ent, size_t ent_len,
const unsigned char *adin, size_t adinlen)
{
unsigned char *entropy = NULL;
size_t entropylen = 0;
if (!ossl_prov_is_running())
return 0;
if (drbg->state != EVP_RAND_STATE_READY) {
/* try to recover from previous errors */
rand_drbg_restart(drbg);
if (drbg->state == EVP_RAND_STATE_ERROR) {
ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);
return 0;
}
if (drbg->state == EVP_RAND_STATE_UNINITIALISED) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED);
return 0;
}
}
if (ent != NULL) {
if (ent_len < drbg->min_entropylen) {
ERR_raise(ERR_LIB_RAND, RAND_R_ENTROPY_OUT_OF_RANGE);
drbg->state = EVP_RAND_STATE_ERROR;
return 0;
}
if (ent_len > drbg->max_entropylen) {
ERR_raise(ERR_LIB_RAND, RAND_R_ENTROPY_INPUT_TOO_LONG);
drbg->state = EVP_RAND_STATE_ERROR;
return 0;
}
}
if (adin == NULL) {
adinlen = 0;
} else if (adinlen > drbg->max_adinlen) {
ERR_raise(ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG);
return 0;
}
drbg->state = EVP_RAND_STATE_ERROR;
drbg->reseed_next_counter = tsan_load(&drbg->reseed_counter);
if (drbg->reseed_next_counter) {
drbg->reseed_next_counter++;
if (!drbg->reseed_next_counter)
drbg->reseed_next_counter = 1;
}
if (ent != NULL) {
#ifdef FIPS_MODULE
/*
* NIST SP-800-90A mandates that entropy *shall not* be provided
* by the consuming application. Instead the data is added as additional
* input.
*
* (NIST SP-800-90Ar1, Sections 9.1 and 9.2)
*/
if (!drbg->reseed(drbg, NULL, 0, ent, ent_len)) {
ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED);
return 0;
}
#else
if (!drbg->reseed(drbg, ent, ent_len, adin, adinlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED);
return 0;
}
/* There isn't much point adding the same additional input twice */
adin = NULL;
adinlen = 0;
#endif
}
/* Reseed using our sources in addition */
entropylen = get_entropy(drbg, &entropy, drbg->strength,
drbg->min_entropylen, drbg->max_entropylen,
prediction_resistance);
if (entropylen < drbg->min_entropylen
|| entropylen > drbg->max_entropylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY);
goto end;
}
if (!drbg->reseed(drbg, entropy, entropylen, adin, adinlen))
goto end;
drbg->state = EVP_RAND_STATE_READY;
drbg->generate_counter = 1;
drbg->reseed_time = time(NULL);
tsan_store(&drbg->reseed_counter, drbg->reseed_next_counter);
if (drbg->parent != NULL)
drbg->parent_reseed_counter = get_parent_reseed_count(drbg);
end:
cleanup_entropy(drbg, entropy, entropylen);
if (drbg->state == EVP_RAND_STATE_READY)
return 1;
return 0;
}
/*
* Generate |outlen| bytes into the buffer at |out|. Reseed if we need
* to or if |prediction_resistance| is set. Additional input can be
* sent in |adin| and |adinlen|.
*
* Requires that drbg->lock is already locked for write, if non-null.
*
* Returns 1 on success, 0 on failure.
*
*/
int ossl_prov_drbg_generate(PROV_DRBG *drbg, unsigned char *out, size_t outlen,
unsigned int strength, int prediction_resistance,
const unsigned char *adin, size_t adinlen)
{
int fork_id;
int reseed_required = 0;
if (!ossl_prov_is_running())
return 0;
if (drbg->state != EVP_RAND_STATE_READY) {
/* try to recover from previous errors */
rand_drbg_restart(drbg);
if (drbg->state == EVP_RAND_STATE_ERROR) {
ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);
return 0;
}
if (drbg->state == EVP_RAND_STATE_UNINITIALISED) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED);
return 0;
}
}
if (strength > drbg->strength) {
ERR_raise(ERR_LIB_PROV, PROV_R_INSUFFICIENT_DRBG_STRENGTH);
return 0;
}
if (outlen > drbg->max_request) {
ERR_raise(ERR_LIB_PROV, PROV_R_REQUEST_TOO_LARGE_FOR_DRBG);
return 0;
}
if (adinlen > drbg->max_adinlen) {
ERR_raise(ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG);
return 0;
}
fork_id = openssl_get_fork_id();
if (drbg->fork_id != fork_id) {
drbg->fork_id = fork_id;
reseed_required = 1;
}
if (drbg->reseed_interval > 0) {
if (drbg->generate_counter >= drbg->reseed_interval)
reseed_required = 1;
}
if (drbg->reseed_time_interval > 0) {
time_t now = time(NULL);
if (now < drbg->reseed_time
|| now - drbg->reseed_time >= drbg->reseed_time_interval)
reseed_required = 1;
}
if (drbg->parent != NULL
&& get_parent_reseed_count(drbg) != drbg->parent_reseed_counter)
reseed_required = 1;
if (reseed_required || prediction_resistance) {
if (!ossl_prov_drbg_reseed(drbg, prediction_resistance, NULL, 0,
adin, adinlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_RESEED_ERROR);
return 0;
}
adin = NULL;
adinlen = 0;
}
if (!drbg->generate(drbg, out, outlen, adin, adinlen)) {
drbg->state = EVP_RAND_STATE_ERROR;
ERR_raise(ERR_LIB_PROV, PROV_R_GENERATE_ERROR);
return 0;
}
drbg->generate_counter++;
return 1;
}
/*
* Restart |drbg|, using the specified entropy or additional input
*
* Tries its best to get the drbg instantiated by all means,
* regardless of its current state.
*
* Optionally, a |buffer| of |len| random bytes can be passed,
* which is assumed to contain at least |entropy| bits of entropy.
*
* If |entropy| > 0, the buffer content is used as entropy input.
*
* If |entropy| == 0, the buffer content is used as additional input
*
* Returns 1 on success, 0 on failure.
*
* This function is used internally only.
*/
static int rand_drbg_restart(PROV_DRBG *drbg)
{
/* repair error state */
if (drbg->state == EVP_RAND_STATE_ERROR)
drbg->uninstantiate(drbg);
/* repair uninitialized state */
if (drbg->state == EVP_RAND_STATE_UNINITIALISED)
/* reinstantiate drbg */
ossl_prov_drbg_instantiate(drbg, drbg->strength, 0, NULL, 0);
return drbg->state == EVP_RAND_STATE_READY;
}
/* Provider support from here down */
static const OSSL_DISPATCH *find_call(const OSSL_DISPATCH *dispatch,
int function)
{
if (dispatch != NULL)
while (dispatch->function_id != 0) {
if (dispatch->function_id == function)
return dispatch;
dispatch++;
}
return NULL;
}
int ossl_drbg_enable_locking(void *vctx)
{
PROV_DRBG *drbg = vctx;
if (drbg != NULL && drbg->lock == NULL) {
if (drbg->parent_enable_locking != NULL)
if (!drbg->parent_enable_locking(drbg->parent)) {
ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED);
return 0;
}
drbg->lock = CRYPTO_THREAD_lock_new();
if (drbg->lock == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_CREATE_LOCK);
return 0;
}
}
return 1;
}
/*
* Allocate memory and initialize a new DRBG. The DRBG is allocated on
* the secure heap if |secure| is nonzero and the secure heap is enabled.
* The |parent|, if not NULL, will be used as random source for reseeding.
* This also requires the parent's provider context and the parent's lock.
*
* Returns a pointer to the new DRBG instance on success, NULL on failure.
*/
PROV_DRBG *ossl_rand_drbg_new
(void *provctx, void *parent, const OSSL_DISPATCH *p_dispatch,
int (*dnew)(PROV_DRBG *ctx),
int (*instantiate)(PROV_DRBG *drbg,
const unsigned char *entropy, size_t entropylen,
const unsigned char *nonce, size_t noncelen,
const unsigned char *pers, size_t perslen),
int (*uninstantiate)(PROV_DRBG *ctx),
int (*reseed)(PROV_DRBG *drbg, const unsigned char *ent, size_t ent_len,
const unsigned char *adin, size_t adin_len),
int (*generate)(PROV_DRBG *, unsigned char *out, size_t outlen,
const unsigned char *adin, size_t adin_len))
{
PROV_DRBG *drbg;
unsigned int p_str;
const OSSL_DISPATCH *pfunc;
if (!ossl_prov_is_running())
return NULL;
drbg = OPENSSL_zalloc(sizeof(*drbg));
if (drbg == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
drbg->provctx = provctx;
drbg->instantiate = instantiate;
drbg->uninstantiate = uninstantiate;
drbg->reseed = reseed;
drbg->generate = generate;
drbg->fork_id = openssl_get_fork_id();
/* Extract parent's functions */
drbg->parent = parent;
if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_ENABLE_LOCKING)) != NULL)
drbg->parent_enable_locking = OSSL_FUNC_rand_enable_locking(pfunc);
if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_LOCK)) != NULL)
drbg->parent_lock = OSSL_FUNC_rand_lock(pfunc);
if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_UNLOCK)) != NULL)
drbg->parent_unlock = OSSL_FUNC_rand_unlock(pfunc);
if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_CTX_PARAMS)) != NULL)
drbg->parent_get_ctx_params = OSSL_FUNC_rand_get_ctx_params(pfunc);
if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_NONCE)) != NULL)
drbg->parent_nonce = OSSL_FUNC_rand_nonce(pfunc);
if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_SEED)) != NULL)
drbg->parent_get_seed = OSSL_FUNC_rand_get_seed(pfunc);
if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_CLEAR_SEED)) != NULL)
drbg->parent_clear_seed = OSSL_FUNC_rand_clear_seed(pfunc);
/* Set some default maximums up */
drbg->max_entropylen = DRBG_MAX_LENGTH;
drbg->max_noncelen = DRBG_MAX_LENGTH;
drbg->max_perslen = DRBG_MAX_LENGTH;
drbg->max_adinlen = DRBG_MAX_LENGTH;
drbg->generate_counter = 1;
drbg->reseed_counter = 1;
drbg->reseed_interval = RESEED_INTERVAL;
drbg->reseed_time_interval = TIME_INTERVAL;
if (!dnew(drbg))
goto err;
if (parent != NULL) {
if (!get_parent_strength(drbg, &p_str))
goto err;
if (drbg->strength > p_str) {
/*
* We currently don't support the algorithm from NIST SP 800-90C
* 10.1.2 to use a weaker DRBG as source
*/
ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK);
goto err;
}
}
#ifdef TSAN_REQUIRES_LOCKING
if (!ossl_drbg_enable_locking(drbg))
goto err;
#endif
return drbg;
err:
ossl_rand_drbg_free(drbg);
return NULL;
}
void ossl_rand_drbg_free(PROV_DRBG *drbg)
{
if (drbg == NULL)
return;
CRYPTO_THREAD_lock_free(drbg->lock);
OPENSSL_free(drbg);
}
int ossl_drbg_get_ctx_params(PROV_DRBG *drbg, OSSL_PARAM params[])
{
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);
if (p != NULL && !OSSL_PARAM_set_int(p, drbg->state))
return 0;
p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);
if (p != NULL && !OSSL_PARAM_set_int(p, drbg->strength))
return 0;
p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_request))
return 0;
p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MIN_ENTROPYLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->min_entropylen))
return 0;
p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_ENTROPYLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_entropylen))
return 0;
p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MIN_NONCELEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->min_noncelen))
return 0;
p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_NONCELEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_noncelen))
return 0;
p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_PERSLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_perslen))
return 0;
p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_ADINLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_adinlen))
return 0;
p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_REQUESTS);
if (p != NULL && !OSSL_PARAM_set_uint(p, drbg->reseed_interval))
return 0;
p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_TIME);
if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time))
return 0;
p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL);
if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time_interval))
return 0;
p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_COUNTER);
if (p != NULL
&& !OSSL_PARAM_set_uint(p, tsan_load(&drbg->reseed_counter)))
return 0;
return 1;
}
int ossl_drbg_set_ctx_params(PROV_DRBG *drbg, const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
if (params == NULL)
return 1;
p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RESEED_REQUESTS);
if (p != NULL && !OSSL_PARAM_get_uint(p, &drbg->reseed_interval))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL);
if (p != NULL && !OSSL_PARAM_get_time_t(p, &drbg->reseed_time_interval))
return 0;
return 1;
}
diff --git a/providers/implementations/signature/rsa_sig.c b/providers/implementations/signature/rsa_sig.c
index 7023a866131e..76516d9a0987 100644
--- a/providers/implementations/signature/rsa_sig.c
+++ b/providers/implementations/signature/rsa_sig.c
@@ -1,1474 +1,1477 @@
/*
- * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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
*/
/*
* RSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/params.h>
#include <openssl/evp.h>
#include <openssl/proverr.h>
#include "internal/cryptlib.h"
#include "internal/nelem.h"
#include "internal/sizes.h"
#include "crypto/rsa.h"
#include "prov/providercommon.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "prov/der_rsa.h"
#include "prov/securitycheck.h"
#define RSA_DEFAULT_DIGEST_NAME OSSL_DIGEST_NAME_SHA1
static OSSL_FUNC_signature_newctx_fn rsa_newctx;
static OSSL_FUNC_signature_sign_init_fn rsa_sign_init;
static OSSL_FUNC_signature_verify_init_fn rsa_verify_init;
static OSSL_FUNC_signature_verify_recover_init_fn rsa_verify_recover_init;
static OSSL_FUNC_signature_sign_fn rsa_sign;
static OSSL_FUNC_signature_verify_fn rsa_verify;
static OSSL_FUNC_signature_verify_recover_fn rsa_verify_recover;
static OSSL_FUNC_signature_digest_sign_init_fn rsa_digest_sign_init;
static OSSL_FUNC_signature_digest_sign_update_fn rsa_digest_signverify_update;
static OSSL_FUNC_signature_digest_sign_final_fn rsa_digest_sign_final;
static OSSL_FUNC_signature_digest_verify_init_fn rsa_digest_verify_init;
static OSSL_FUNC_signature_digest_verify_update_fn rsa_digest_signverify_update;
static OSSL_FUNC_signature_digest_verify_final_fn rsa_digest_verify_final;
static OSSL_FUNC_signature_freectx_fn rsa_freectx;
static OSSL_FUNC_signature_dupctx_fn rsa_dupctx;
static OSSL_FUNC_signature_get_ctx_params_fn rsa_get_ctx_params;
static OSSL_FUNC_signature_gettable_ctx_params_fn rsa_gettable_ctx_params;
static OSSL_FUNC_signature_set_ctx_params_fn rsa_set_ctx_params;
static OSSL_FUNC_signature_settable_ctx_params_fn rsa_settable_ctx_params;
static OSSL_FUNC_signature_get_ctx_md_params_fn rsa_get_ctx_md_params;
static OSSL_FUNC_signature_gettable_ctx_md_params_fn rsa_gettable_ctx_md_params;
static OSSL_FUNC_signature_set_ctx_md_params_fn rsa_set_ctx_md_params;
static OSSL_FUNC_signature_settable_ctx_md_params_fn rsa_settable_ctx_md_params;
static OSSL_ITEM padding_item[] = {
{ RSA_PKCS1_PADDING, OSSL_PKEY_RSA_PAD_MODE_PKCSV15 },
{ RSA_NO_PADDING, OSSL_PKEY_RSA_PAD_MODE_NONE },
{ RSA_X931_PADDING, OSSL_PKEY_RSA_PAD_MODE_X931 },
{ RSA_PKCS1_PSS_PADDING, OSSL_PKEY_RSA_PAD_MODE_PSS },
{ 0, NULL }
};
/*
* 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;
char *propq;
RSA *rsa;
int operation;
/*
* Flag to determine if the hash function can be changed (1) or not (0)
* Because it's dangerous to change during a DigestSign or DigestVerify
* operation, this flag is cleared by their Init function, and set again
* by their Final function.
*/
unsigned int flag_allow_md : 1;
unsigned int mgf1_md_set : 1;
/* main digest */
EVP_MD *md;
EVP_MD_CTX *mdctx;
int mdnid;
char mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */
/* RSA padding mode */
int pad_mode;
/* message digest for MGF1 */
EVP_MD *mgf1_md;
int mgf1_mdnid;
char mgf1_mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */
/* PSS salt length */
int saltlen;
/* Minimum salt length or -1 if no PSS parameter restriction */
int min_saltlen;
/* Temp buffer */
unsigned char *tbuf;
} PROV_RSA_CTX;
/* True if PSS parameters are restricted */
#define rsa_pss_restricted(prsactx) (prsactx->min_saltlen != -1)
static size_t rsa_get_md_size(const PROV_RSA_CTX *prsactx)
{
if (prsactx->md != NULL)
return EVP_MD_get_size(prsactx->md);
return 0;
}
static int rsa_check_padding(const PROV_RSA_CTX *prsactx,
const char *mdname, const char *mgf1_mdname,
int mdnid)
{
switch(prsactx->pad_mode) {
case RSA_NO_PADDING:
if (mdname != NULL || mdnid != NID_undef) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE);
return 0;
}
break;
case RSA_X931_PADDING:
if (RSA_X931_hash_id(mdnid) == -1) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_X931_DIGEST);
return 0;
}
break;
case RSA_PKCS1_PSS_PADDING:
if (rsa_pss_restricted(prsactx))
if ((mdname != NULL && !EVP_MD_is_a(prsactx->md, mdname))
|| (mgf1_mdname != NULL
&& !EVP_MD_is_a(prsactx->mgf1_md, mgf1_mdname))) {
ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
return 0;
}
break;
default:
break;
}
return 1;
}
static int rsa_check_parameters(PROV_RSA_CTX *prsactx, int min_saltlen)
{
if (prsactx->pad_mode == RSA_PKCS1_PSS_PADDING) {
int max_saltlen;
/* See if minimum salt length exceeds maximum possible */
max_saltlen = RSA_size(prsactx->rsa) - EVP_MD_get_size(prsactx->md);
if ((RSA_bits(prsactx->rsa) & 0x7) == 1)
max_saltlen--;
if (min_saltlen < 0 || min_saltlen > max_saltlen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
return 0;
}
prsactx->min_saltlen = min_saltlen;
}
return 1;
}
static void *rsa_newctx(void *provctx, const char *propq)
{
PROV_RSA_CTX *prsactx = NULL;
char *propq_copy = NULL;
if (!ossl_prov_is_running())
return NULL;
if ((prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX))) == NULL
|| (propq != NULL
&& (propq_copy = OPENSSL_strdup(propq)) == NULL)) {
OPENSSL_free(prsactx);
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
prsactx->libctx = PROV_LIBCTX_OF(provctx);
prsactx->flag_allow_md = 1;
prsactx->propq = propq_copy;
/* Maximum for sign, auto for verify */
prsactx->saltlen = RSA_PSS_SALTLEN_AUTO;
prsactx->min_saltlen = -1;
return prsactx;
}
static int rsa_pss_compute_saltlen(PROV_RSA_CTX *ctx)
{
int saltlen = ctx->saltlen;
if (saltlen == RSA_PSS_SALTLEN_DIGEST) {
saltlen = EVP_MD_get_size(ctx->md);
} else if (saltlen == RSA_PSS_SALTLEN_AUTO || saltlen == RSA_PSS_SALTLEN_MAX) {
saltlen = RSA_size(ctx->rsa) - EVP_MD_get_size(ctx->md) - 2;
if ((RSA_bits(ctx->rsa) & 0x7) == 1)
saltlen--;
}
if (saltlen < 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
return -1;
} else if (saltlen < ctx->min_saltlen) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL,
"minimum salt length: %d, actual salt length: %d",
ctx->min_saltlen, saltlen);
return -1;
}
return saltlen;
}
static unsigned char *rsa_generate_signature_aid(PROV_RSA_CTX *ctx,
unsigned char *aid_buf,
size_t buf_len,
size_t *aid_len)
{
WPACKET pkt;
unsigned char *aid = NULL;
int saltlen;
RSA_PSS_PARAMS_30 pss_params;
int ret;
if (!WPACKET_init_der(&pkt, aid_buf, buf_len)) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
switch(ctx->pad_mode) {
case RSA_PKCS1_PADDING:
ret = ossl_DER_w_algorithmIdentifier_MDWithRSAEncryption(&pkt, -1,
ctx->mdnid);
if (ret > 0) {
break;
} else if (ret == 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
goto cleanup;
}
ERR_raise_data(ERR_LIB_PROV, ERR_R_UNSUPPORTED,
"Algorithm ID generation - md NID: %d",
ctx->mdnid);
goto cleanup;
case RSA_PKCS1_PSS_PADDING:
saltlen = rsa_pss_compute_saltlen(ctx);
if (saltlen < 0)
goto cleanup;
if (!ossl_rsa_pss_params_30_set_defaults(&pss_params)
|| !ossl_rsa_pss_params_30_set_hashalg(&pss_params, ctx->mdnid)
|| !ossl_rsa_pss_params_30_set_maskgenhashalg(&pss_params,
ctx->mgf1_mdnid)
|| !ossl_rsa_pss_params_30_set_saltlen(&pss_params, saltlen)
|| !ossl_DER_w_algorithmIdentifier_RSA_PSS(&pkt, -1,
RSA_FLAG_TYPE_RSASSAPSS,
&pss_params)) {
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
goto cleanup;
}
break;
default:
ERR_raise_data(ERR_LIB_PROV, ERR_R_UNSUPPORTED,
"Algorithm ID generation - pad mode: %d",
ctx->pad_mode);
goto cleanup;
}
if (WPACKET_finish(&pkt)) {
WPACKET_get_total_written(&pkt, aid_len);
aid = WPACKET_get_curr(&pkt);
}
cleanup:
WPACKET_cleanup(&pkt);
return aid;
}
static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname,
const char *mdprops)
{
if (mdprops == NULL)
mdprops = ctx->propq;
if (mdname != NULL) {
EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
int md_nid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md,
sha1_allowed);
size_t mdname_len = strlen(mdname);
if (md == NULL
|| md_nid <= 0
|| !rsa_check_padding(ctx, mdname, NULL, md_nid)
|| mdname_len >= sizeof(ctx->mdname)) {
if (md == NULL)
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
"%s could not be fetched", mdname);
if (md_nid <= 0)
ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
"digest=%s", mdname);
if (mdname_len >= sizeof(ctx->mdname))
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
"%s exceeds name buffer length", mdname);
EVP_MD_free(md);
return 0;
}
if (!ctx->flag_allow_md) {
if (ctx->mdname[0] != '\0' && !EVP_MD_is_a(md, ctx->mdname)) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
"digest %s != %s", mdname, ctx->mdname);
EVP_MD_free(md);
return 0;
}
EVP_MD_free(md);
return 1;
}
if (!ctx->mgf1_md_set) {
if (!EVP_MD_up_ref(md)) {
EVP_MD_free(md);
return 0;
}
EVP_MD_free(ctx->mgf1_md);
ctx->mgf1_md = md;
ctx->mgf1_mdnid = md_nid;
OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname));
}
EVP_MD_CTX_free(ctx->mdctx);
EVP_MD_free(ctx->md);
ctx->mdctx = NULL;
ctx->md = md;
ctx->mdnid = md_nid;
OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname));
}
return 1;
}
static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname,
const char *mdprops)
{
size_t len;
EVP_MD *md = NULL;
int mdnid;
if (mdprops == NULL)
mdprops = ctx->propq;
if ((md = EVP_MD_fetch(ctx->libctx, mdname, mdprops)) == NULL) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
"%s could not be fetched", mdname);
return 0;
}
/* The default for mgf1 is SHA1 - so allow SHA1 */
if ((mdnid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md, 1)) <= 0
|| !rsa_check_padding(ctx, NULL, mdname, mdnid)) {
if (mdnid <= 0)
ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
"digest=%s", mdname);
EVP_MD_free(md);
return 0;
}
len = OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname));
if (len >= sizeof(ctx->mgf1_mdname)) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
"%s exceeds name buffer length", mdname);
EVP_MD_free(md);
return 0;
}
EVP_MD_free(ctx->mgf1_md);
ctx->mgf1_md = md;
ctx->mgf1_mdnid = mdnid;
ctx->mgf1_md_set = 1;
return 1;
}
static int rsa_signverify_init(void *vprsactx, void *vrsa,
const OSSL_PARAM params[], int operation)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
if (!ossl_prov_is_running() || prsactx == NULL)
return 0;
if (vrsa == NULL && prsactx->rsa == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
return 0;
}
if (vrsa != NULL) {
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;
}
prsactx->operation = operation;
/* Maximum for sign, auto for verify */
prsactx->saltlen = RSA_PSS_SALTLEN_AUTO;
prsactx->min_saltlen = -1;
switch (RSA_test_flags(prsactx->rsa, RSA_FLAG_TYPE_MASK)) {
case RSA_FLAG_TYPE_RSA:
prsactx->pad_mode = RSA_PKCS1_PADDING;
break;
case RSA_FLAG_TYPE_RSASSAPSS:
prsactx->pad_mode = RSA_PKCS1_PSS_PADDING;
{
const RSA_PSS_PARAMS_30 *pss =
ossl_rsa_get0_pss_params_30(prsactx->rsa);
if (!ossl_rsa_pss_params_30_is_unrestricted(pss)) {
int md_nid = ossl_rsa_pss_params_30_hashalg(pss);
int mgf1md_nid = ossl_rsa_pss_params_30_maskgenhashalg(pss);
int min_saltlen = ossl_rsa_pss_params_30_saltlen(pss);
const char *mdname, *mgf1mdname;
size_t len;
mdname = ossl_rsa_oaeppss_nid2name(md_nid);
mgf1mdname = ossl_rsa_oaeppss_nid2name(mgf1md_nid);
if (mdname == NULL) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
"PSS restrictions lack hash algorithm");
return 0;
}
if (mgf1mdname == NULL) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
"PSS restrictions lack MGF1 hash algorithm");
return 0;
}
len = OPENSSL_strlcpy(prsactx->mdname, mdname,
sizeof(prsactx->mdname));
if (len >= sizeof(prsactx->mdname)) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
"hash algorithm name too long");
return 0;
}
len = OPENSSL_strlcpy(prsactx->mgf1_mdname, mgf1mdname,
sizeof(prsactx->mgf1_mdname));
if (len >= sizeof(prsactx->mgf1_mdname)) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
"MGF1 hash algorithm name too long");
return 0;
}
prsactx->saltlen = min_saltlen;
/* call rsa_setup_mgf1_md before rsa_setup_md to avoid duplication */
if (!rsa_setup_mgf1_md(prsactx, mgf1mdname, prsactx->propq)
|| !rsa_setup_md(prsactx, mdname, prsactx->propq)
|| !rsa_check_parameters(prsactx, min_saltlen))
return 0;
}
}
break;
default:
ERR_raise(ERR_LIB_RSA, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (!rsa_set_ctx_params(prsactx, params))
return 0;
return 1;
}
static int setup_tbuf(PROV_RSA_CTX *ctx)
{
if (ctx->tbuf != NULL)
return 1;
if ((ctx->tbuf = OPENSSL_malloc(RSA_size(ctx->rsa))) == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
static void clean_tbuf(PROV_RSA_CTX *ctx)
{
if (ctx->tbuf != NULL)
OPENSSL_cleanse(ctx->tbuf, RSA_size(ctx->rsa));
}
static void free_tbuf(PROV_RSA_CTX *ctx)
{
clean_tbuf(ctx);
OPENSSL_free(ctx->tbuf);
ctx->tbuf = NULL;
}
static int rsa_sign_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[])
{
if (!ossl_prov_is_running())
return 0;
return rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_SIGN);
}
static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen,
size_t sigsize, const unsigned char *tbs, size_t tbslen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
int ret;
size_t rsasize = RSA_size(prsactx->rsa);
size_t mdsize = rsa_get_md_size(prsactx);
if (!ossl_prov_is_running())
return 0;
if (sig == NULL) {
*siglen = rsasize;
return 1;
}
if (sigsize < rsasize) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SIGNATURE_SIZE,
"is %zu, should be at least %zu", sigsize, rsasize);
return 0;
}
if (mdsize != 0) {
if (tbslen != mdsize) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
return 0;
}
#ifndef FIPS_MODULE
if (EVP_MD_is_a(prsactx->md, OSSL_DIGEST_NAME_MDC2)) {
unsigned int sltmp;
if (prsactx->pad_mode != RSA_PKCS1_PADDING) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
"only PKCS#1 padding supported with MDC2");
return 0;
}
ret = RSA_sign_ASN1_OCTET_STRING(0, tbs, tbslen, sig, &sltmp,
prsactx->rsa);
if (ret <= 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
return 0;
}
ret = sltmp;
goto end;
}
#endif
switch (prsactx->pad_mode) {
case RSA_X931_PADDING:
if ((size_t)RSA_size(prsactx->rsa) < tbslen + 1) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL,
"RSA key size = %d, expected minimum = %d",
RSA_size(prsactx->rsa), tbslen + 1);
return 0;
}
if (!setup_tbuf(prsactx)) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(prsactx->tbuf, tbs, tbslen);
prsactx->tbuf[tbslen] = RSA_X931_hash_id(prsactx->mdnid);
ret = RSA_private_encrypt(tbslen + 1, prsactx->tbuf,
sig, prsactx->rsa, RSA_X931_PADDING);
clean_tbuf(prsactx);
break;
case RSA_PKCS1_PADDING:
{
unsigned int sltmp;
ret = RSA_sign(prsactx->mdnid, tbs, tbslen, sig, &sltmp,
prsactx->rsa);
if (ret <= 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
return 0;
}
ret = sltmp;
}
break;
case RSA_PKCS1_PSS_PADDING:
/* Check PSS restrictions */
if (rsa_pss_restricted(prsactx)) {
switch (prsactx->saltlen) {
case RSA_PSS_SALTLEN_DIGEST:
if (prsactx->min_saltlen > EVP_MD_get_size(prsactx->md)) {
ERR_raise_data(ERR_LIB_PROV,
PROV_R_PSS_SALTLEN_TOO_SMALL,
"minimum salt length set to %d, "
"but the digest only gives %d",
prsactx->min_saltlen,
EVP_MD_get_size(prsactx->md));
return 0;
}
/* FALLTHRU */
default:
if (prsactx->saltlen >= 0
&& prsactx->saltlen < prsactx->min_saltlen) {
ERR_raise_data(ERR_LIB_PROV,
PROV_R_PSS_SALTLEN_TOO_SMALL,
"minimum salt length set to %d, but the"
"actual salt length is only set to %d",
prsactx->min_saltlen,
prsactx->saltlen);
return 0;
}
break;
}
}
if (!setup_tbuf(prsactx))
return 0;
if (!RSA_padding_add_PKCS1_PSS_mgf1(prsactx->rsa,
prsactx->tbuf, tbs,
prsactx->md, prsactx->mgf1_md,
prsactx->saltlen)) {
ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
return 0;
}
ret = RSA_private_encrypt(RSA_size(prsactx->rsa), prsactx->tbuf,
sig, prsactx->rsa, RSA_NO_PADDING);
clean_tbuf(prsactx);
break;
default:
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
"Only X.931, PKCS#1 v1.5 or PSS padding allowed");
return 0;
}
} else {
ret = RSA_private_encrypt(tbslen, tbs, sig, prsactx->rsa,
prsactx->pad_mode);
}
#ifndef FIPS_MODULE
end:
#endif
if (ret <= 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
return 0;
}
*siglen = ret;
return 1;
}
static int rsa_verify_recover_init(void *vprsactx, void *vrsa,
const OSSL_PARAM params[])
{
if (!ossl_prov_is_running())
return 0;
return rsa_signverify_init(vprsactx, vrsa, params,
EVP_PKEY_OP_VERIFYRECOVER);
}
static int rsa_verify_recover(void *vprsactx,
unsigned char *rout,
size_t *routlen,
size_t routsize,
const unsigned char *sig,
size_t siglen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
int ret;
if (!ossl_prov_is_running())
return 0;
if (rout == NULL) {
*routlen = RSA_size(prsactx->rsa);
return 1;
}
if (prsactx->md != NULL) {
switch (prsactx->pad_mode) {
case RSA_X931_PADDING:
if (!setup_tbuf(prsactx))
return 0;
ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa,
RSA_X931_PADDING);
if (ret < 1) {
ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
return 0;
}
ret--;
if (prsactx->tbuf[ret] != RSA_X931_hash_id(prsactx->mdnid)) {
ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
return 0;
}
if (ret != EVP_MD_get_size(prsactx->md)) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH,
"Should be %d, but got %d",
EVP_MD_get_size(prsactx->md), ret);
return 0;
}
*routlen = ret;
if (rout != prsactx->tbuf) {
if (routsize < (size_t)ret) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL,
"buffer size is %d, should be %d",
routsize, ret);
return 0;
}
memcpy(rout, prsactx->tbuf, ret);
}
break;
case RSA_PKCS1_PADDING:
{
size_t sltmp;
ret = ossl_rsa_verify(prsactx->mdnid, NULL, 0, rout, &sltmp,
sig, siglen, prsactx->rsa);
if (ret <= 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
return 0;
}
ret = sltmp;
}
break;
default:
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
"Only X.931 or PKCS#1 v1.5 padding allowed");
return 0;
}
} else {
ret = RSA_public_decrypt(siglen, sig, rout, prsactx->rsa,
prsactx->pad_mode);
if (ret < 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
return 0;
}
}
*routlen = ret;
return 1;
}
static int rsa_verify_init(void *vprsactx, void *vrsa,
const OSSL_PARAM params[])
{
if (!ossl_prov_is_running())
return 0;
return rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_VERIFY);
}
static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen,
const unsigned char *tbs, size_t tbslen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
size_t rslen;
if (!ossl_prov_is_running())
return 0;
if (prsactx->md != NULL) {
switch (prsactx->pad_mode) {
case RSA_PKCS1_PADDING:
if (!RSA_verify(prsactx->mdnid, tbs, tbslen, sig, siglen,
prsactx->rsa)) {
ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
return 0;
}
return 1;
case RSA_X931_PADDING:
if (!setup_tbuf(prsactx))
return 0;
if (rsa_verify_recover(prsactx, prsactx->tbuf, &rslen, 0,
sig, siglen) <= 0)
return 0;
break;
case RSA_PKCS1_PSS_PADDING:
{
int ret;
size_t mdsize;
/*
* We need to check this for the RSA_verify_PKCS1_PSS_mgf1()
* call
*/
mdsize = rsa_get_md_size(prsactx);
if (tbslen != mdsize) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH,
"Should be %d, but got %d",
mdsize, tbslen);
return 0;
}
if (!setup_tbuf(prsactx))
return 0;
ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf,
prsactx->rsa, RSA_NO_PADDING);
if (ret <= 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
return 0;
}
ret = RSA_verify_PKCS1_PSS_mgf1(prsactx->rsa, tbs,
prsactx->md, prsactx->mgf1_md,
prsactx->tbuf,
prsactx->saltlen);
if (ret <= 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
return 0;
}
return 1;
}
default:
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
"Only X.931, PKCS#1 v1.5 or PSS padding allowed");
return 0;
}
} else {
+ int ret;
+
if (!setup_tbuf(prsactx))
return 0;
- rslen = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa,
- prsactx->pad_mode);
- if (rslen == 0) {
+ ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa,
+ prsactx->pad_mode);
+ if (ret <= 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB);
return 0;
}
+ rslen = (size_t)ret;
}
if ((rslen != tbslen) || memcmp(tbs, prsactx->tbuf, rslen))
return 0;
return 1;
}
static int rsa_digest_signverify_init(void *vprsactx, const char *mdname,
void *vrsa, const OSSL_PARAM params[],
int operation)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
if (!ossl_prov_is_running())
return 0;
if (!rsa_signverify_init(vprsactx, vrsa, params, operation))
return 0;
if (mdname != NULL
/* was rsa_setup_md already called in rsa_signverify_init()? */
&& (mdname[0] == '\0' || OPENSSL_strcasecmp(prsactx->mdname, mdname) != 0)
&& !rsa_setup_md(prsactx, mdname, prsactx->propq))
return 0;
prsactx->flag_allow_md = 0;
if (prsactx->mdctx == NULL) {
prsactx->mdctx = EVP_MD_CTX_new();
if (prsactx->mdctx == NULL)
goto error;
}
if (!EVP_DigestInit_ex2(prsactx->mdctx, prsactx->md, params))
goto error;
return 1;
error:
EVP_MD_CTX_free(prsactx->mdctx);
prsactx->mdctx = NULL;
return 0;
}
static int rsa_digest_signverify_update(void *vprsactx,
const unsigned char *data,
size_t datalen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
if (prsactx == NULL || prsactx->mdctx == NULL)
return 0;
return EVP_DigestUpdate(prsactx->mdctx, data, datalen);
}
static int rsa_digest_sign_init(void *vprsactx, const char *mdname,
void *vrsa, const OSSL_PARAM params[])
{
if (!ossl_prov_is_running())
return 0;
return rsa_digest_signverify_init(vprsactx, mdname, vrsa,
params, EVP_PKEY_OP_SIGN);
}
static int rsa_digest_sign_final(void *vprsactx, unsigned char *sig,
size_t *siglen, size_t sigsize)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int dlen = 0;
if (!ossl_prov_is_running() || prsactx == NULL)
return 0;
prsactx->flag_allow_md = 1;
if (prsactx->mdctx == NULL)
return 0;
/*
* If sig is NULL then we're just finding out the sig size. Other fields
* are ignored. Defer to rsa_sign.
*/
if (sig != NULL) {
/*
* The digests used here are all known (see rsa_get_md_nid()), so they
* should not exceed the internal buffer size of EVP_MAX_MD_SIZE.
*/
if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
return 0;
}
return rsa_sign(vprsactx, sig, siglen, sigsize, digest, (size_t)dlen);
}
static int rsa_digest_verify_init(void *vprsactx, const char *mdname,
void *vrsa, const OSSL_PARAM params[])
{
if (!ossl_prov_is_running())
return 0;
return rsa_digest_signverify_init(vprsactx, mdname, vrsa,
params, EVP_PKEY_OP_VERIFY);
}
int rsa_digest_verify_final(void *vprsactx, const unsigned char *sig,
size_t siglen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int dlen = 0;
if (!ossl_prov_is_running())
return 0;
if (prsactx == NULL)
return 0;
prsactx->flag_allow_md = 1;
if (prsactx->mdctx == NULL)
return 0;
/*
* The digests used here are all known (see rsa_get_md_nid()), so they
* should not exceed the internal buffer size of EVP_MAX_MD_SIZE.
*/
if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
return 0;
return rsa_verify(vprsactx, sig, siglen, digest, (size_t)dlen);
}
static void rsa_freectx(void *vprsactx)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
if (prsactx == NULL)
return;
EVP_MD_CTX_free(prsactx->mdctx);
EVP_MD_free(prsactx->md);
EVP_MD_free(prsactx->mgf1_md);
OPENSSL_free(prsactx->propq);
free_tbuf(prsactx);
RSA_free(prsactx->rsa);
OPENSSL_clear_free(prsactx, sizeof(*prsactx));
}
static void *rsa_dupctx(void *vprsactx)
{
PROV_RSA_CTX *srcctx = (PROV_RSA_CTX *)vprsactx;
PROV_RSA_CTX *dstctx;
if (!ossl_prov_is_running())
return NULL;
dstctx = OPENSSL_zalloc(sizeof(*srcctx));
if (dstctx == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
*dstctx = *srcctx;
dstctx->rsa = NULL;
dstctx->md = NULL;
dstctx->mdctx = NULL;
dstctx->tbuf = NULL;
dstctx->propq = NULL;
if (srcctx->rsa != NULL && !RSA_up_ref(srcctx->rsa))
goto err;
dstctx->rsa = srcctx->rsa;
if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
goto err;
dstctx->md = srcctx->md;
if (srcctx->mgf1_md != NULL && !EVP_MD_up_ref(srcctx->mgf1_md))
goto err;
dstctx->mgf1_md = srcctx->mgf1_md;
if (srcctx->mdctx != NULL) {
dstctx->mdctx = EVP_MD_CTX_new();
if (dstctx->mdctx == NULL
|| !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))
goto err;
}
if (srcctx->propq != NULL) {
dstctx->propq = OPENSSL_strdup(srcctx->propq);
if (dstctx->propq == NULL)
goto err;
}
return dstctx;
err:
rsa_freectx(dstctx);
return NULL;
}
static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
OSSL_PARAM *p;
if (prsactx == NULL)
return 0;
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
if (p != NULL) {
/* The Algorithm Identifier of the combined signature algorithm */
unsigned char aid_buf[128];
unsigned char *aid;
size_t aid_len;
aid = rsa_generate_signature_aid(prsactx, aid_buf,
sizeof(aid_buf), &aid_len);
if (aid == NULL || !OSSL_PARAM_set_octet_string(p, aid, aid_len))
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
if (p != NULL)
switch (p->data_type) {
case OSSL_PARAM_INTEGER:
if (!OSSL_PARAM_set_int(p, prsactx->pad_mode))
return 0;
break;
case OSSL_PARAM_UTF8_STRING:
{
int i;
const char *word = NULL;
for (i = 0; padding_item[i].id != 0; i++) {
if (prsactx->pad_mode == (int)padding_item[i].id) {
word = padding_item[i].ptr;
break;
}
}
if (word != NULL) {
if (!OSSL_PARAM_set_utf8_string(p, word))
return 0;
} else {
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
}
}
break;
default:
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mdname))
return 0;
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST);
if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mgf1_mdname))
return 0;
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN);
if (p != NULL) {
if (p->data_type == OSSL_PARAM_INTEGER) {
if (!OSSL_PARAM_set_int(p, prsactx->saltlen))
return 0;
} else if (p->data_type == OSSL_PARAM_UTF8_STRING) {
const char *value = NULL;
switch (prsactx->saltlen) {
case RSA_PSS_SALTLEN_DIGEST:
value = OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST;
break;
case RSA_PSS_SALTLEN_MAX:
value = OSSL_PKEY_RSA_PSS_SALT_LEN_MAX;
break;
case RSA_PSS_SALTLEN_AUTO:
value = OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO;
break;
default:
{
int len = BIO_snprintf(p->data, p->data_size, "%d",
prsactx->saltlen);
if (len <= 0)
return 0;
p->return_size = len;
break;
}
}
if (value != NULL
&& !OSSL_PARAM_set_utf8_string(p, value))
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_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *rsa_gettable_ctx_params(ossl_unused void *vprsactx,
ossl_unused void *provctx)
{
return known_gettable_ctx_params;
}
static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
const OSSL_PARAM *p;
int pad_mode;
int saltlen;
char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = NULL;
char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = NULL;
char mgf1mdname[OSSL_MAX_NAME_SIZE] = "", *pmgf1mdname = NULL;
char mgf1mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmgf1mdprops = NULL;
if (prsactx == NULL)
return 0;
if (params == NULL)
return 1;
pad_mode = prsactx->pad_mode;
saltlen = prsactx->saltlen;
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
if (p != NULL) {
const OSSL_PARAM *propsp =
OSSL_PARAM_locate_const(params,
OSSL_SIGNATURE_PARAM_PROPERTIES);
pmdname = mdname;
if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
return 0;
if (propsp != NULL) {
pmdprops = mdprops;
if (!OSSL_PARAM_get_utf8_string(propsp,
&pmdprops, sizeof(mdprops)))
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
if (p != NULL) {
const char *err_extra_text = NULL;
switch (p->data_type) {
case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
if (!OSSL_PARAM_get_int(p, &pad_mode))
return 0;
break;
case OSSL_PARAM_UTF8_STRING:
{
int i;
if (p->data == NULL)
return 0;
for (i = 0; padding_item[i].id != 0; i++) {
if (strcmp(p->data, padding_item[i].ptr) == 0) {
pad_mode = padding_item[i].id;
break;
}
}
}
break;
default:
return 0;
}
switch (pad_mode) {
case RSA_PKCS1_OAEP_PADDING:
/*
* OAEP padding is for asymmetric cipher only so is not compatible
* with signature use.
*/
err_extra_text = "OAEP padding not allowed for signing / verifying";
goto bad_pad;
case RSA_PKCS1_PSS_PADDING:
if ((prsactx->operation
& (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)) == 0) {
err_extra_text =
"PSS padding only allowed for sign and verify operations";
goto bad_pad;
}
break;
case RSA_PKCS1_PADDING:
err_extra_text = "PKCS#1 padding not allowed with RSA-PSS";
goto cont;
case RSA_NO_PADDING:
err_extra_text = "No padding not allowed with RSA-PSS";
goto cont;
case RSA_X931_PADDING:
err_extra_text = "X.931 padding not allowed with RSA-PSS";
cont:
if (RSA_test_flags(prsactx->rsa,
RSA_FLAG_TYPE_MASK) == RSA_FLAG_TYPE_RSA)
break;
/* FALLTHRU */
default:
bad_pad:
if (err_extra_text == NULL)
ERR_raise(ERR_LIB_PROV,
PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
else
ERR_raise_data(ERR_LIB_PROV,
PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE,
err_extra_text);
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN);
if (p != NULL) {
if (pad_mode != RSA_PKCS1_PSS_PADDING) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED,
"PSS saltlen can only be specified if "
"PSS padding has been specified first");
return 0;
}
switch (p->data_type) {
case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
if (!OSSL_PARAM_get_int(p, &saltlen))
return 0;
break;
case OSSL_PARAM_UTF8_STRING:
if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST) == 0)
saltlen = RSA_PSS_SALTLEN_DIGEST;
else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_MAX) == 0)
saltlen = RSA_PSS_SALTLEN_MAX;
else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO) == 0)
saltlen = RSA_PSS_SALTLEN_AUTO;
else
saltlen = atoi(p->data);
break;
default:
return 0;
}
/*
* RSA_PSS_SALTLEN_MAX seems curiously named in this check.
* Contrary to what it's name suggests, it's the currently
* lowest saltlen number possible.
*/
if (saltlen < RSA_PSS_SALTLEN_MAX) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
return 0;
}
if (rsa_pss_restricted(prsactx)) {
switch (saltlen) {
case RSA_PSS_SALTLEN_AUTO:
if (prsactx->operation == EVP_PKEY_OP_VERIFY) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH,
"Cannot use autodetected salt length");
return 0;
}
break;
case RSA_PSS_SALTLEN_DIGEST:
if (prsactx->min_saltlen > EVP_MD_get_size(prsactx->md)) {
ERR_raise_data(ERR_LIB_PROV,
PROV_R_PSS_SALTLEN_TOO_SMALL,
"Should be more than %d, but would be "
"set to match digest size (%d)",
prsactx->min_saltlen,
EVP_MD_get_size(prsactx->md));
return 0;
}
break;
default:
if (saltlen >= 0 && saltlen < prsactx->min_saltlen) {
ERR_raise_data(ERR_LIB_PROV,
PROV_R_PSS_SALTLEN_TOO_SMALL,
"Should be more than %d, "
"but would be set to %d",
prsactx->min_saltlen, saltlen);
return 0;
}
}
}
}
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST);
if (p != NULL) {
const OSSL_PARAM *propsp =
OSSL_PARAM_locate_const(params,
OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES);
pmgf1mdname = mgf1mdname;
if (!OSSL_PARAM_get_utf8_string(p, &pmgf1mdname, sizeof(mgf1mdname)))
return 0;
if (propsp != NULL) {
pmgf1mdprops = mgf1mdprops;
if (!OSSL_PARAM_get_utf8_string(propsp,
&pmgf1mdprops, sizeof(mgf1mdprops)))
return 0;
}
if (pad_mode != RSA_PKCS1_PSS_PADDING) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MGF1_MD);
return 0;
}
}
prsactx->saltlen = saltlen;
prsactx->pad_mode = pad_mode;
if (prsactx->md == NULL && pmdname == NULL
&& pad_mode == RSA_PKCS1_PSS_PADDING)
pmdname = RSA_DEFAULT_DIGEST_NAME;
if (pmgf1mdname != NULL
&& !rsa_setup_mgf1_md(prsactx, pmgf1mdname, pmgf1mdprops))
return 0;
if (pmdname != NULL) {
if (!rsa_setup_md(prsactx, pmdname, pmdprops))
return 0;
} else {
if (!rsa_check_padding(prsactx, NULL, NULL, prsactx->mdnid))
return 0;
}
return 1;
}
static const OSSL_PARAM settable_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM settable_ctx_params_no_digest[] = {
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *rsa_settable_ctx_params(void *vprsactx,
ossl_unused void *provctx)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
if (prsactx != NULL && !prsactx->flag_allow_md)
return settable_ctx_params_no_digest;
return settable_ctx_params;
}
static int rsa_get_ctx_md_params(void *vprsactx, OSSL_PARAM *params)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
if (prsactx->mdctx == NULL)
return 0;
return EVP_MD_CTX_get_params(prsactx->mdctx, params);
}
static const OSSL_PARAM *rsa_gettable_ctx_md_params(void *vprsactx)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
if (prsactx->md == NULL)
return 0;
return EVP_MD_gettable_ctx_params(prsactx->md);
}
static int rsa_set_ctx_md_params(void *vprsactx, const OSSL_PARAM params[])
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
if (prsactx->mdctx == NULL)
return 0;
return EVP_MD_CTX_set_params(prsactx->mdctx, params);
}
static const OSSL_PARAM *rsa_settable_ctx_md_params(void *vprsactx)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
if (prsactx->md == NULL)
return 0;
return EVP_MD_settable_ctx_params(prsactx->md);
}
const OSSL_DISPATCH ossl_rsa_signature_functions[] = {
{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))rsa_newctx },
{ OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))rsa_sign_init },
{ OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))rsa_sign },
{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))rsa_verify_init },
{ OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))rsa_verify },
{ OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT,
(void (*)(void))rsa_verify_recover_init },
{ OSSL_FUNC_SIGNATURE_VERIFY_RECOVER,
(void (*)(void))rsa_verify_recover },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
(void (*)(void))rsa_digest_sign_init },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
(void (*)(void))rsa_digest_signverify_update },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
(void (*)(void))rsa_digest_sign_final },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
(void (*)(void))rsa_digest_verify_init },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
(void (*)(void))rsa_digest_signverify_update },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
(void (*)(void))rsa_digest_verify_final },
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))rsa_freectx },
{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))rsa_dupctx },
{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))rsa_get_ctx_params },
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
(void (*)(void))rsa_gettable_ctx_params },
{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))rsa_set_ctx_params },
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
(void (*)(void))rsa_settable_ctx_params },
{ OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
(void (*)(void))rsa_get_ctx_md_params },
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
(void (*)(void))rsa_gettable_ctx_md_params },
{ OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
(void (*)(void))rsa_set_ctx_md_params },
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
(void (*)(void))rsa_settable_ctx_md_params },
{ 0, NULL }
};
diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c
index 7f3d1a7f0ddf..79de0219ec7b 100644
--- a/ssl/record/rec_layer_d1.c
+++ b/ssl/record/rec_layer_d1.c
@@ -1,1053 +1,1051 @@
/*
- * Copyright 2005-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-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 <errno.h>
#include "../ssl_local.h"
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include "record_local.h"
#include "internal/packet.h"
#include "internal/cryptlib.h"
int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl)
{
DTLS_RECORD_LAYER *d;
if ((d = OPENSSL_malloc(sizeof(*d))) == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
rl->d = d;
d->unprocessed_rcds.q = pqueue_new();
d->processed_rcds.q = pqueue_new();
d->buffered_app_data.q = pqueue_new();
if (d->unprocessed_rcds.q == NULL || d->processed_rcds.q == NULL
|| d->buffered_app_data.q == NULL) {
pqueue_free(d->unprocessed_rcds.q);
pqueue_free(d->processed_rcds.q);
pqueue_free(d->buffered_app_data.q);
OPENSSL_free(d);
rl->d = NULL;
return 0;
}
return 1;
}
void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl)
{
if (rl->d == NULL)
return;
DTLS_RECORD_LAYER_clear(rl);
pqueue_free(rl->d->unprocessed_rcds.q);
pqueue_free(rl->d->processed_rcds.q);
pqueue_free(rl->d->buffered_app_data.q);
OPENSSL_free(rl->d);
rl->d = NULL;
}
void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl)
{
DTLS_RECORD_LAYER *d;
pitem *item = NULL;
DTLS1_RECORD_DATA *rdata;
pqueue *unprocessed_rcds;
pqueue *processed_rcds;
pqueue *buffered_app_data;
d = rl->d;
while ((item = pqueue_pop(d->unprocessed_rcds.q)) != NULL) {
rdata = (DTLS1_RECORD_DATA *)item->data;
OPENSSL_free(rdata->rbuf.buf);
OPENSSL_free(item->data);
pitem_free(item);
}
while ((item = pqueue_pop(d->processed_rcds.q)) != NULL) {
rdata = (DTLS1_RECORD_DATA *)item->data;
if (rl->s->options & SSL_OP_CLEANSE_PLAINTEXT)
OPENSSL_cleanse(rdata->rbuf.buf, rdata->rbuf.len);
OPENSSL_free(rdata->rbuf.buf);
OPENSSL_free(item->data);
pitem_free(item);
}
while ((item = pqueue_pop(d->buffered_app_data.q)) != NULL) {
rdata = (DTLS1_RECORD_DATA *)item->data;
if (rl->s->options & SSL_OP_CLEANSE_PLAINTEXT)
OPENSSL_cleanse(rdata->rbuf.buf, rdata->rbuf.len);
OPENSSL_free(rdata->rbuf.buf);
OPENSSL_free(item->data);
pitem_free(item);
}
unprocessed_rcds = d->unprocessed_rcds.q;
processed_rcds = d->processed_rcds.q;
buffered_app_data = d->buffered_app_data.q;
memset(d, 0, sizeof(*d));
d->unprocessed_rcds.q = unprocessed_rcds;
d->processed_rcds.q = processed_rcds;
d->buffered_app_data.q = buffered_app_data;
}
void DTLS_RECORD_LAYER_set_saved_w_epoch(RECORD_LAYER *rl, unsigned short e)
{
if (e == rl->d->w_epoch - 1) {
memcpy(rl->d->curr_write_sequence,
rl->write_sequence, sizeof(rl->write_sequence));
memcpy(rl->write_sequence,
rl->d->last_write_sequence, sizeof(rl->write_sequence));
} else if (e == rl->d->w_epoch + 1) {
memcpy(rl->d->last_write_sequence,
rl->write_sequence, sizeof(unsigned char[8]));
memcpy(rl->write_sequence,
rl->d->curr_write_sequence, sizeof(rl->write_sequence));
}
rl->d->w_epoch = e;
}
void DTLS_RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, unsigned char *seq)
{
memcpy(rl->write_sequence, seq, SEQ_NUM_SIZE);
}
/* copy buffered record into SSL structure */
static int dtls1_copy_record(SSL *s, pitem *item)
{
DTLS1_RECORD_DATA *rdata;
rdata = (DTLS1_RECORD_DATA *)item->data;
SSL3_BUFFER_release(&s->rlayer.rbuf);
s->rlayer.packet = rdata->packet;
s->rlayer.packet_length = rdata->packet_length;
memcpy(&s->rlayer.rbuf, &(rdata->rbuf), sizeof(SSL3_BUFFER));
memcpy(&s->rlayer.rrec, &(rdata->rrec), sizeof(SSL3_RECORD));
/* Set proper sequence number for mac calculation */
memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6);
return 1;
}
int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
{
DTLS1_RECORD_DATA *rdata;
pitem *item;
/* Limit the size of the queue to prevent DOS attacks */
if (pqueue_size(queue->q) >= 100)
return 0;
rdata = OPENSSL_malloc(sizeof(*rdata));
item = pitem_new(priority, rdata);
if (rdata == NULL || item == NULL) {
OPENSSL_free(rdata);
pitem_free(item);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
rdata->packet = s->rlayer.packet;
rdata->packet_length = s->rlayer.packet_length;
memcpy(&(rdata->rbuf), &s->rlayer.rbuf, sizeof(SSL3_BUFFER));
memcpy(&(rdata->rrec), &s->rlayer.rrec, sizeof(SSL3_RECORD));
item->data = rdata;
#ifndef OPENSSL_NO_SCTP
/* Store bio_dgram_sctp_rcvinfo struct */
if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
(SSL_get_state(s) == TLS_ST_SR_FINISHED
|| SSL_get_state(s) == TLS_ST_CR_FINISHED)) {
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO,
sizeof(rdata->recordinfo), &rdata->recordinfo);
}
#endif
s->rlayer.packet = NULL;
s->rlayer.packet_length = 0;
memset(&s->rlayer.rbuf, 0, sizeof(s->rlayer.rbuf));
memset(&s->rlayer.rrec, 0, sizeof(s->rlayer.rrec));
if (!ssl3_setup_buffers(s)) {
/* SSLfatal() already called */
OPENSSL_free(rdata->rbuf.buf);
OPENSSL_free(rdata);
pitem_free(item);
return -1;
}
if (pqueue_insert(queue->q, item) == NULL) {
/* Must be a duplicate so ignore it */
OPENSSL_free(rdata->rbuf.buf);
OPENSSL_free(rdata);
pitem_free(item);
}
return 1;
}
int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
{
pitem *item;
item = pqueue_pop(queue->q);
if (item) {
dtls1_copy_record(s, item);
OPENSSL_free(item->data);
pitem_free(item);
return 1;
}
return 0;
}
/*
* retrieve a buffered record that belongs to the new epoch, i.e., not
* processed yet
*/
#define dtls1_get_unprocessed_record(s) \
dtls1_retrieve_buffered_record((s), \
&((s)->rlayer.d->unprocessed_rcds))
int dtls1_process_buffered_records(SSL *s)
{
pitem *item;
SSL3_BUFFER *rb;
SSL3_RECORD *rr;
DTLS1_BITMAP *bitmap;
unsigned int is_next_epoch;
int replayok = 1;
item = pqueue_peek(s->rlayer.d->unprocessed_rcds.q);
if (item) {
/* Check if epoch is current. */
if (s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch)
return 1; /* Nothing to do. */
rr = RECORD_LAYER_get_rrec(&s->rlayer);
rb = RECORD_LAYER_get_rbuf(&s->rlayer);
if (SSL3_BUFFER_get_left(rb) > 0) {
/*
* We've still got data from the current packet to read. There could
* be a record from the new epoch in it - so don't overwrite it
* with the unprocessed records yet (we'll do it when we've
* finished reading the current packet).
*/
return 1;
}
/* Process all the records. */
while (pqueue_peek(s->rlayer.d->unprocessed_rcds.q)) {
dtls1_get_unprocessed_record(s);
bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
if (bitmap == NULL) {
/*
* Should not happen. This will only ever be NULL when the
* current record is from a different epoch. But that cannot
* be the case because we already checked the epoch above
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
#ifndef OPENSSL_NO_SCTP
/* Only do replay check if no SCTP bio */
if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
#endif
{
/*
* Check whether this is a repeat, or aged record. We did this
* check once already when we first received the record - but
* we might have updated the window since then due to
* records we subsequently processed.
*/
replayok = dtls1_record_replay_check(s, bitmap);
}
if (!replayok || !dtls1_process_record(s, bitmap)) {
if (ossl_statem_in_error(s)) {
/* dtls1_process_record called SSLfatal() */
return 0;
}
/* dump this record */
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer);
continue;
}
if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds),
SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < 0) {
/* SSLfatal() already called */
return 0;
}
}
}
/*
* sync epoch numbers once all the unprocessed records have been
* processed
*/
s->rlayer.d->processed_rcds.epoch = s->rlayer.d->r_epoch;
s->rlayer.d->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1;
return 1;
}
/*-
* Return up to 'len' payload bytes received in 'type' records.
* 'type' is one of the following:
*
* - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
* - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us)
* - 0 (during a shutdown, no data has to be returned)
*
* If we don't have stored data to work from, read a SSL/TLS record first
* (possibly multiple records if we still don't have anything to return).
*
* This function must handle any surprises the peer may have for us, such as
* Alert records (e.g. close_notify) or renegotiation requests. ChangeCipherSpec
* messages are treated as if they were handshake messages *if* the |recd_type|
* argument is non NULL.
* Also if record payloads contain fragments too small to process, we store
* them until there is enough for the respective protocol (the record protocol
* may use arbitrary fragmentation and even interleaving):
* Change cipher spec protocol
* just 1 byte needed, no need for keeping anything stored
* Alert protocol
* 2 bytes needed (AlertLevel, AlertDescription)
* Handshake protocol
* 4 bytes needed (HandshakeType, uint24 length) -- we just have
* to detect unexpected Client Hello and Hello Request messages
* here, anything else is handled by higher layers
* Application data protocol
* none of our business
*/
int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
size_t len, int peek, size_t *readbytes)
{
int i, j, iret;
size_t n;
SSL3_RECORD *rr;
void (*cb) (const SSL *ssl, int type2, int val) = NULL;
if (!SSL3_BUFFER_is_initialised(&s->rlayer.rbuf)) {
/* Not initialized yet */
if (!ssl3_setup_buffers(s)) {
/* SSLfatal() already called */
return -1;
}
}
if ((type && (type != SSL3_RT_APPLICATION_DATA) &&
(type != SSL3_RT_HANDSHAKE)) ||
(peek && (type != SSL3_RT_APPLICATION_DATA))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) {
/* type == SSL3_RT_APPLICATION_DATA */
i = s->handshake_func(s);
/* SSLfatal() already called if appropriate */
if (i < 0)
return i;
if (i == 0)
return -1;
}
start:
s->rwstate = SSL_NOTHING;
/*-
* s->s3.rrec.type - is the type of record
* s->s3.rrec.data, - data
* s->s3.rrec.off, - offset into 'data' for next read
* s->s3.rrec.length, - number of bytes.
*/
rr = s->rlayer.rrec;
/*
* We are not handshaking and have no data yet, so process data buffered
* during the last handshake in advance, if any.
*/
if (SSL_is_init_finished(s) && SSL3_RECORD_get_length(rr) == 0) {
pitem *item;
item = pqueue_pop(s->rlayer.d->buffered_app_data.q);
if (item) {
#ifndef OPENSSL_NO_SCTP
/* Restore bio_dgram_sctp_rcvinfo struct */
if (BIO_dgram_is_sctp(SSL_get_rbio(s))) {
DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data;
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO,
sizeof(rdata->recordinfo), &rdata->recordinfo);
}
#endif
dtls1_copy_record(s, item);
OPENSSL_free(item->data);
pitem_free(item);
}
}
/* Check for timeout */
if (dtls1_handle_timeout(s) > 0) {
goto start;
} else if (ossl_statem_in_error(s)) {
/* dtls1_handle_timeout() has failed with a fatal error */
return -1;
}
/* get new packet if necessary */
if ((SSL3_RECORD_get_length(rr) == 0)
|| (s->rlayer.rstate == SSL_ST_READ_BODY)) {
RECORD_LAYER_set_numrpipes(&s->rlayer, 0);
iret = dtls1_get_record(s);
if (iret <= 0) {
iret = dtls1_read_failed(s, iret);
/*
* Anything other than a timeout is an error. SSLfatal() already
* called if appropriate.
*/
if (iret <= 0)
return iret;
else
goto start;
}
RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
}
/*
* Reset the count of consecutive warning alerts if we've got a non-empty
* record that isn't an alert.
*/
if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT
&& SSL3_RECORD_get_length(rr) != 0)
s->rlayer.alert_count = 0;
/* we now have a packet which can be read and processed */
if (s->s3.change_cipher_spec /* set when we receive ChangeCipherSpec,
* reset by ssl3_get_finished */
&& (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) {
/*
* We now have application data between CCS and Finished. Most likely
* the packets were reordered on their way, so buffer the application
* data for later processing rather than dropping the connection.
*/
if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data),
SSL3_RECORD_get_seq_num(rr)) < 0) {
/* SSLfatal() already called */
return -1;
}
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
goto start;
}
/*
* If the other end has shut down, throw anything we read away (even in
* 'peek' mode)
*/
if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
s->rwstate = SSL_NOTHING;
return 0;
}
if (type == SSL3_RECORD_get_type(rr)
|| (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
&& type == SSL3_RT_HANDSHAKE && recvd_type != NULL)) {
/*
* SSL3_RT_APPLICATION_DATA or
* SSL3_RT_HANDSHAKE or
* SSL3_RT_CHANGE_CIPHER_SPEC
*/
/*
* make sure that we are not getting application data when we are
* doing a handshake for the first time
*/
if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
(s->enc_read_ctx == NULL)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_APP_DATA_IN_HANDSHAKE);
return -1;
}
if (recvd_type != NULL)
*recvd_type = SSL3_RECORD_get_type(rr);
if (len == 0) {
/*
* Mark a zero length record as read. This ensures multiple calls to
* SSL_read() with a zero length buffer will eventually cause
* SSL_pending() to report data as being available.
*/
if (SSL3_RECORD_get_length(rr) == 0)
SSL3_RECORD_set_read(rr);
return 0;
}
if (len > SSL3_RECORD_get_length(rr))
n = SSL3_RECORD_get_length(rr);
else
n = len;
memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n);
if (peek) {
if (SSL3_RECORD_get_length(rr) == 0)
SSL3_RECORD_set_read(rr);
} else {
if (s->options & SSL_OP_CLEANSE_PLAINTEXT)
OPENSSL_cleanse(&(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n);
SSL3_RECORD_sub_length(rr, n);
SSL3_RECORD_add_off(rr, n);
if (SSL3_RECORD_get_length(rr) == 0) {
s->rlayer.rstate = SSL_ST_READ_HEADER;
SSL3_RECORD_set_off(rr, 0);
SSL3_RECORD_set_read(rr);
}
}
#ifndef OPENSSL_NO_SCTP
/*
* We might had to delay a close_notify alert because of reordered
* app data. If there was an alert and there is no message to read
* anymore, finally set shutdown.
*/
if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
s->d1->shutdown_received
&& BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)) <= 0) {
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
return 0;
}
#endif
*readbytes = n;
return 1;
}
/*
* If we get here, then type != rr->type; if we have a handshake message,
* then it was unexpected (Hello Request or Client Hello).
*/
if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
unsigned int alert_level, alert_descr;
unsigned char *alert_bytes = SSL3_RECORD_get_data(rr)
+ SSL3_RECORD_get_off(rr);
PACKET alert;
if (!PACKET_buf_init(&alert, alert_bytes, SSL3_RECORD_get_length(rr))
|| !PACKET_get_1(&alert, &alert_level)
|| !PACKET_get_1(&alert, &alert_descr)
|| PACKET_remaining(&alert) != 0) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_INVALID_ALERT);
return -1;
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_bytes, 2, s,
s->msg_callback_arg);
if (s->info_callback != NULL)
cb = s->info_callback;
else if (s->ctx->info_callback != NULL)
cb = s->ctx->info_callback;
if (cb != NULL) {
j = (alert_level << 8) | alert_descr;
cb(s, SSL_CB_READ_ALERT, j);
}
if (alert_level == SSL3_AL_WARNING) {
s->s3.warn_alert = alert_descr;
SSL3_RECORD_set_read(rr);
s->rlayer.alert_count++;
if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_TOO_MANY_WARN_ALERTS);
return -1;
}
if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
#ifndef OPENSSL_NO_SCTP
/*
* With SCTP and streams the socket may deliver app data
* after a close_notify alert. We have to check this first so
* that nothing gets discarded.
*/
if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)) > 0) {
s->d1->shutdown_received = 1;
s->rwstate = SSL_READING;
BIO_clear_retry_flags(SSL_get_rbio(s));
BIO_set_retry_read(SSL_get_rbio(s));
return -1;
}
#endif
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
return 0;
}
} else if (alert_level == SSL3_AL_FATAL) {
s->rwstate = SSL_NOTHING;
s->s3.fatal_alert = alert_descr;
SSLfatal_data(s, SSL_AD_NO_ALERT,
SSL_AD_REASON_OFFSET + alert_descr,
"SSL alert number %d", alert_descr);
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
SSL3_RECORD_set_read(rr);
SSL_CTX_remove_session(s->session_ctx, s->session);
return 0;
} else {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_UNKNOWN_ALERT_TYPE);
return -1;
}
goto start;
}
if (s->shutdown & SSL_SENT_SHUTDOWN) { /* but we have not received a
* shutdown */
s->rwstate = SSL_NOTHING;
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
return 0;
}
if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) {
/*
* We can't process a CCS now, because previous handshake messages
* are still missing, so just drop it.
*/
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
goto start;
}
/*
* Unexpected handshake message (Client Hello, or protocol violation)
*/
if ((SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) &&
!ossl_statem_get_in_handshake(s)) {
struct hm_header_st msg_hdr;
/*
* This may just be a stale retransmit. Also sanity check that we have
* at least enough record bytes for a message header
*/
if (SSL3_RECORD_get_epoch(rr) != s->rlayer.d->r_epoch
|| SSL3_RECORD_get_length(rr) < DTLS1_HM_HEADER_LENGTH) {
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
goto start;
}
dtls1_get_message_header(rr->data, &msg_hdr);
/*
* If we are server, we may have a repeated FINISHED of the client
* here, then retransmit our CCS and FINISHED.
*/
if (msg_hdr.type == SSL3_MT_FINISHED) {
if (dtls1_check_timeout_num(s) < 0) {
/* SSLfatal) already called */
return -1;
}
if (dtls1_retransmit_buffered_messages(s) <= 0) {
/* Fail if we encountered a fatal error */
if (ossl_statem_in_error(s))
return -1;
}
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {
/* no read-ahead left? */
BIO *bio;
s->rwstate = SSL_READING;
bio = SSL_get_rbio(s);
BIO_clear_retry_flags(bio);
BIO_set_retry_read(bio);
return -1;
}
}
goto start;
}
/*
* To get here we must be trying to read app data but found handshake
* data. But if we're trying to read app data, and we're not in init
* (which is tested for at the top of this function) then init must be
* finished
*/
if (!ossl_assert(SSL_is_init_finished(s))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
/* We found handshake data, so we're going back into init */
ossl_statem_set_in_init(s, 1);
i = s->handshake_func(s);
/* SSLfatal() called if appropriate */
if (i < 0)
return i;
if (i == 0)
return -1;
if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {
/* no read-ahead left? */
BIO *bio;
/*
* In the case where we try to read application data, but we
* trigger an SSL handshake, we return -1 with the retry
* option set. Otherwise renegotiation may cause nasty
* problems in the blocking world
*/
s->rwstate = SSL_READING;
bio = SSL_get_rbio(s);
BIO_clear_retry_flags(bio);
BIO_set_retry_read(bio);
return -1;
}
}
goto start;
}
switch (SSL3_RECORD_get_type(rr)) {
default:
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_RECORD);
return -1;
case SSL3_RT_CHANGE_CIPHER_SPEC:
case SSL3_RT_ALERT:
case SSL3_RT_HANDSHAKE:
/*
* we already handled all of these, with the possible exception of
* SSL3_RT_HANDSHAKE when ossl_statem_get_in_handshake(s) is true, but
* that should not happen when type != rr->type
*/
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, ERR_R_INTERNAL_ERROR);
return -1;
case SSL3_RT_APPLICATION_DATA:
/*
* At this point, we were expecting handshake data, but have
* application data. If the library was running inside ssl3_read()
* (i.e. in_read_app_data is set) and it makes sense to read
* application data at this point (session renegotiation not yet
* started), we will indulge it.
*/
if (s->s3.in_read_app_data &&
(s->s3.total_renegotiations != 0) &&
ossl_statem_app_data_allowed(s)) {
s->s3.in_read_app_data = 2;
return -1;
} else {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_RECORD);
return -1;
}
}
/* not reached */
}
/*
* Call this to write data in records of type 'type' It will return <= 0 if
* not all data has been sent or non-blocking IO.
*/
int dtls1_write_bytes(SSL *s, int type, const void *buf, size_t len,
size_t *written)
{
int i;
if (!ossl_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
s->rwstate = SSL_NOTHING;
i = do_dtls1_write(s, type, buf, len, 0, written);
return i;
}
int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
size_t len, int create_empty_fragment, size_t *written)
{
unsigned char *p, *pseq;
int i, mac_size, clear = 0;
size_t prefix_len = 0;
int eivlen;
SSL3_RECORD wr;
SSL3_BUFFER *wb;
SSL_SESSION *sess;
wb = &s->rlayer.wbuf[0];
/*
* DTLS writes whole datagrams, so there can't be anything left in
* the buffer.
*/
if (!ossl_assert(SSL3_BUFFER_get_left(wb) == 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
/* If we have an alert to send, lets send it */
if (s->s3.alert_dispatch) {
i = s->method->ssl_dispatch_alert(s);
if (i <= 0)
return i;
/* if it went, fall through and send more stuff */
}
if (len == 0 && !create_empty_fragment)
return 0;
if (len > ssl_get_max_send_fragment(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE);
return 0;
}
sess = s->session;
if ((sess == NULL)
|| (s->enc_write_ctx == NULL)
|| (EVP_MD_CTX_get0_md(s->write_hash) == NULL))
clear = 1;
if (clear)
mac_size = 0;
else {
mac_size = EVP_MD_CTX_get_size(s->write_hash);
if (mac_size < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE);
return -1;
}
}
p = SSL3_BUFFER_get_buf(wb) + prefix_len;
/* write the header */
*(p++) = type & 0xff;
SSL3_RECORD_set_type(&wr, type);
/*
* Special case: for hello verify request, client version 1.0 and we
* haven't decided which version to use yet send back using version 1.0
* header: otherwise some clients will ignore it.
*/
if (s->method->version == DTLS_ANY_VERSION &&
s->max_proto_version != DTLS1_BAD_VER) {
*(p++) = DTLS1_VERSION >> 8;
*(p++) = DTLS1_VERSION & 0xff;
} else {
*(p++) = s->version >> 8;
*(p++) = s->version & 0xff;
}
/* field where we are to write out packet epoch, seq num and len */
pseq = p;
p += 10;
/* Explicit IV length, block ciphers appropriate version flag */
if (s->enc_write_ctx) {
int mode = EVP_CIPHER_CTX_get_mode(s->enc_write_ctx);
if (mode == EVP_CIPH_CBC_MODE) {
eivlen = EVP_CIPHER_CTX_get_iv_length(s->enc_write_ctx);
if (eivlen < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
return -1;
}
if (eivlen <= 1)
eivlen = 0;
}
/* Need explicit part of IV for GCM mode */
else if (mode == EVP_CIPH_GCM_MODE)
eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
else if (mode == EVP_CIPH_CCM_MODE)
eivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
else
eivlen = 0;
} else
eivlen = 0;
/* lets setup the record stuff. */
SSL3_RECORD_set_data(&wr, p + eivlen); /* make room for IV in case of CBC */
SSL3_RECORD_set_length(&wr, len);
SSL3_RECORD_set_input(&wr, (unsigned char *)buf);
/*
* we now 'read' from wr.input, wr.length bytes into wr.data
*/
/* first we compress */
if (s->compress != NULL) {
if (!ssl3_do_compress(s, &wr)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_COMPRESSION_FAILURE);
return -1;
}
} else {
memcpy(SSL3_RECORD_get_data(&wr), SSL3_RECORD_get_input(&wr),
SSL3_RECORD_get_length(&wr));
SSL3_RECORD_reset_input(&wr);
}
/*
* we should still have the output to wr.data and the input from
* wr.input. Length should be wr.length. wr.data still points in the
* wb->buf
*/
if (!SSL_WRITE_ETM(s) && mac_size != 0) {
if (!s->method->ssl3_enc->mac(s, &wr,
&(p[SSL3_RECORD_get_length(&wr) + eivlen]),
1)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
SSL3_RECORD_add_length(&wr, mac_size);
}
/* this is true regardless of mac size */
SSL3_RECORD_set_data(&wr, p);
SSL3_RECORD_reset_input(&wr);
if (eivlen)
SSL3_RECORD_add_length(&wr, eivlen);
if (s->method->ssl3_enc->enc(s, &wr, 1, 1, NULL, mac_size) < 1) {
if (!ossl_statem_in_error(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
}
return -1;
}
if (SSL_WRITE_ETM(s) && mac_size != 0) {
if (!s->method->ssl3_enc->mac(s, &wr,
&(p[SSL3_RECORD_get_length(&wr)]), 1)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
SSL3_RECORD_add_length(&wr, mac_size);
}
/* record length after mac and block padding */
/* there's only one epoch between handshake and app data */
s2n(s->rlayer.d->w_epoch, pseq);
memcpy(pseq, &(s->rlayer.write_sequence[2]), 6);
pseq += 6;
s2n(SSL3_RECORD_get_length(&wr), pseq);
if (s->msg_callback)
s->msg_callback(1, 0, SSL3_RT_HEADER, pseq - DTLS1_RT_HEADER_LENGTH,
DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
/*
* we should now have wr.data pointing to the encrypted data, which is
* wr->length long
*/
SSL3_RECORD_set_type(&wr, type); /* not needed but helps for debugging */
SSL3_RECORD_add_length(&wr, DTLS1_RT_HEADER_LENGTH);
ssl3_record_sequence_update(&(s->rlayer.write_sequence[0]));
if (create_empty_fragment) {
/*
* we are in a recursive call; just return the length, don't write
* out anything here
*/
*written = wr.length;
return 1;
}
/* now let's set up wb */
SSL3_BUFFER_set_left(wb, prefix_len + SSL3_RECORD_get_length(&wr));
SSL3_BUFFER_set_offset(wb, 0);
/*
* memorize arguments so that ssl3_write_pending can detect bad write
* retries later
*/
s->rlayer.wpend_tot = len;
s->rlayer.wpend_buf = buf;
s->rlayer.wpend_type = type;
s->rlayer.wpend_ret = len;
/* we now just need to write the buffer. Calls SSLfatal() as required. */
return ssl3_write_pending(s, type, buf, len, written);
}
DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
unsigned int *is_next_epoch)
{
*is_next_epoch = 0;
/* In current epoch, accept HM, CCS, DATA, & ALERT */
if (rr->epoch == s->rlayer.d->r_epoch)
return &s->rlayer.d->bitmap;
/*
- * Only HM and ALERT messages can be from the next epoch and only if we
- * have already processed all of the unprocessed records from the last
- * epoch
+ * We can only handle messages from the next epoch if we have already
+ * processed all of the unprocessed records from the previous epoch
*/
- else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1) &&
- s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch &&
- (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
+ else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1)
+ && s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch) {
*is_next_epoch = 1;
return &s->rlayer.d->next_bitmap;
}
return NULL;
}
void dtls1_reset_seq_numbers(SSL *s, int rw)
{
unsigned char *seq;
unsigned int seq_bytes = sizeof(s->rlayer.read_sequence);
if (rw & SSL3_CC_READ) {
seq = s->rlayer.read_sequence;
s->rlayer.d->r_epoch++;
memcpy(&s->rlayer.d->bitmap, &s->rlayer.d->next_bitmap,
sizeof(s->rlayer.d->bitmap));
memset(&s->rlayer.d->next_bitmap, 0, sizeof(s->rlayer.d->next_bitmap));
/*
* We must not use any buffered messages received from the previous
* epoch
*/
dtls1_clear_received_buffer(s);
} else {
seq = s->rlayer.write_sequence;
memcpy(s->rlayer.d->last_write_sequence, seq,
sizeof(s->rlayer.write_sequence));
s->rlayer.d->w_epoch++;
}
memset(seq, 0, seq_bytes);
}
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index 4121f3b2ae1c..3baf820761a6 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -1,1834 +1,1815 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <limits.h>
#include <errno.h>
#include "../ssl_local.h"
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <openssl/rand.h>
#include "record_local.h"
#include "internal/packet.h"
#include "internal/cryptlib.h"
#if defined(OPENSSL_SMALL_FOOTPRINT) || \
!( defined(AES_ASM) && ( \
defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64) ) \
)
# undef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0
#endif
void RECORD_LAYER_init(RECORD_LAYER *rl, SSL *s)
{
rl->s = s;
RECORD_LAYER_set_first_record(&s->rlayer);
SSL3_RECORD_clear(rl->rrec, SSL_MAX_PIPELINES);
}
void RECORD_LAYER_clear(RECORD_LAYER *rl)
{
rl->rstate = SSL_ST_READ_HEADER;
/*
* Do I need to clear read_ahead? As far as I can tell read_ahead did not
* previously get reset by SSL_clear...so I'll keep it that way..but is
* that right?
*/
rl->packet = NULL;
rl->packet_length = 0;
rl->wnum = 0;
memset(rl->handshake_fragment, 0, sizeof(rl->handshake_fragment));
rl->handshake_fragment_len = 0;
rl->wpend_tot = 0;
rl->wpend_type = 0;
rl->wpend_ret = 0;
rl->wpend_buf = NULL;
SSL3_BUFFER_clear(&rl->rbuf);
ssl3_release_write_buffer(rl->s);
rl->numrpipes = 0;
SSL3_RECORD_clear(rl->rrec, SSL_MAX_PIPELINES);
RECORD_LAYER_reset_read_sequence(rl);
RECORD_LAYER_reset_write_sequence(rl);
if (rl->d)
DTLS_RECORD_LAYER_clear(rl);
}
void RECORD_LAYER_release(RECORD_LAYER *rl)
{
if (SSL3_BUFFER_is_initialised(&rl->rbuf))
ssl3_release_read_buffer(rl->s);
if (rl->numwpipes > 0)
ssl3_release_write_buffer(rl->s);
SSL3_RECORD_release(rl->rrec, SSL_MAX_PIPELINES);
}
/* Checks if we have unprocessed read ahead data pending */
int RECORD_LAYER_read_pending(const RECORD_LAYER *rl)
{
return SSL3_BUFFER_get_left(&rl->rbuf) != 0;
}
/* Checks if we have decrypted unread record data pending */
int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl)
{
size_t curr_rec = 0, num_recs = RECORD_LAYER_get_numrpipes(rl);
const SSL3_RECORD *rr = rl->rrec;
while (curr_rec < num_recs && SSL3_RECORD_is_read(&rr[curr_rec]))
curr_rec++;
return curr_rec < num_recs;
}
int RECORD_LAYER_write_pending(const RECORD_LAYER *rl)
{
return (rl->numwpipes > 0)
&& SSL3_BUFFER_get_left(&rl->wbuf[rl->numwpipes - 1]) != 0;
}
void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl)
{
memset(rl->read_sequence, 0, sizeof(rl->read_sequence));
}
void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl)
{
memset(rl->write_sequence, 0, sizeof(rl->write_sequence));
}
size_t ssl3_pending(const SSL *s)
{
size_t i, num = 0;
if (s->rlayer.rstate == SSL_ST_READ_BODY)
return 0;
/* Take into account DTLS buffered app data */
if (SSL_IS_DTLS(s)) {
DTLS1_RECORD_DATA *rdata;
pitem *item, *iter;
iter = pqueue_iterator(s->rlayer.d->buffered_app_data.q);
while ((item = pqueue_next(&iter)) != NULL) {
rdata = item->data;
num += rdata->rrec.length;
}
}
for (i = 0; i < RECORD_LAYER_get_numrpipes(&s->rlayer); i++) {
if (SSL3_RECORD_get_type(&s->rlayer.rrec[i])
!= SSL3_RT_APPLICATION_DATA)
return num;
num += SSL3_RECORD_get_length(&s->rlayer.rrec[i]);
}
return num;
}
void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len)
{
ctx->default_read_buf_len = len;
}
void SSL_set_default_read_buffer_len(SSL *s, size_t len)
{
SSL3_BUFFER_set_default_len(RECORD_LAYER_get_rbuf(&s->rlayer), len);
}
const char *SSL_rstate_string_long(const SSL *s)
{
switch (s->rlayer.rstate) {
case SSL_ST_READ_HEADER:
return "read header";
case SSL_ST_READ_BODY:
return "read body";
case SSL_ST_READ_DONE:
return "read done";
default:
return "unknown";
}
}
const char *SSL_rstate_string(const SSL *s)
{
switch (s->rlayer.rstate) {
case SSL_ST_READ_HEADER:
return "RH";
case SSL_ST_READ_BODY:
return "RB";
case SSL_ST_READ_DONE:
return "RD";
default:
return "unknown";
}
}
/*
* Return values are as per SSL_read()
*/
int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold,
size_t *readbytes)
{
/*
* If extend == 0, obtain new n-byte packet; if extend == 1, increase
* packet by another n bytes. The packet will be in the sub-array of
* s->rlayer.rbuf.buf specified by s->rlayer.packet and
* s->rlayer.packet_length. (If s->rlayer.read_ahead is set, 'max' bytes may
* be stored in rbuf [plus s->rlayer.packet_length bytes if extend == 1].)
* if clearold == 1, move the packet to the start of the buffer; if
* clearold == 0 then leave any old packets where they were
*/
size_t len, left, align = 0;
unsigned char *pkt;
SSL3_BUFFER *rb;
if (n == 0)
return 0;
rb = &s->rlayer.rbuf;
if (rb->buf == NULL)
if (!ssl3_setup_read_buffer(s)) {
/* SSLfatal() already called */
return -1;
}
left = rb->left;
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
align = (size_t)rb->buf + SSL3_RT_HEADER_LENGTH;
align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
#endif
if (!extend) {
/* start with empty packet ... */
if (left == 0)
rb->offset = align;
- else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH) {
- /*
- * check if next packet length is large enough to justify payload
- * alignment...
- */
- pkt = rb->buf + rb->offset;
- if (pkt[0] == SSL3_RT_APPLICATION_DATA
- && (pkt[3] << 8 | pkt[4]) >= 128) {
- /*
- * Note that even if packet is corrupted and its length field
- * is insane, we can only be led to wrong decision about
- * whether memmove will occur or not. Header values has no
- * effect on memmove arguments and therefore no buffer
- * overrun can be triggered.
- */
- memmove(rb->buf + align, pkt, left);
- rb->offset = align;
- }
- }
+
s->rlayer.packet = rb->buf + rb->offset;
s->rlayer.packet_length = 0;
/* ... now we can act as if 'extend' was set */
}
len = s->rlayer.packet_length;
pkt = rb->buf + align;
/*
* Move any available bytes to front of buffer: 'len' bytes already
* pointed to by 'packet', 'left' extra ones at the end
*/
if (s->rlayer.packet != pkt && clearold == 1) {
memmove(pkt, s->rlayer.packet, len + left);
s->rlayer.packet = pkt;
rb->offset = len + align;
}
/*
* For DTLS/UDP reads should not span multiple packets because the read
* operation returns the whole packet at once (as long as it fits into
* the buffer).
*/
if (SSL_IS_DTLS(s)) {
if (left == 0 && extend)
return 0;
if (left > 0 && n > left)
n = left;
}
/* if there is enough in the buffer from a previous read, take some */
if (left >= n) {
s->rlayer.packet_length += n;
rb->left = left - n;
rb->offset += n;
*readbytes = n;
return 1;
}
/* else we need to read more data */
if (n > rb->len - rb->offset) {
/* does not happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
/*
* Ktls always reads full records.
* Also, we always act like read_ahead is set for DTLS.
*/
if (!BIO_get_ktls_recv(s->rbio) && !s->rlayer.read_ahead
&& !SSL_IS_DTLS(s)) {
/* ignore max parameter */
max = n;
} else {
if (max < n)
max = n;
if (max > rb->len - rb->offset)
max = rb->len - rb->offset;
}
while (left < n) {
size_t bioread = 0;
int ret;
/*
* Now we have len+left bytes at the front of s->s3.rbuf.buf and
* need to read in more until we have len+n (up to len+max if
* possible)
*/
clear_sys_error();
if (s->rbio != NULL) {
s->rwstate = SSL_READING;
ret = BIO_read(s->rbio, pkt + len + left, max - left);
if (ret >= 0)
bioread = ret;
if (ret <= 0
&& !BIO_should_retry(s->rbio)
&& BIO_eof(s->rbio)) {
if (s->options & SSL_OP_IGNORE_UNEXPECTED_EOF) {
SSL_set_shutdown(s, SSL_RECEIVED_SHUTDOWN);
s->s3.warn_alert = SSL_AD_CLOSE_NOTIFY;
} else {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_UNEXPECTED_EOF_WHILE_READING);
}
}
} else {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_READ_BIO_NOT_SET);
ret = -1;
}
if (ret <= 0) {
rb->left = left;
if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s))
if (len + left == 0)
ssl3_release_read_buffer(s);
return ret;
}
left += bioread;
/*
* reads should *never* span multiple packets for DTLS because the
* underlying transport protocol is message oriented as opposed to
* byte oriented as in the TLS case.
*/
if (SSL_IS_DTLS(s)) {
if (n > left)
n = left; /* makes the while condition false */
}
}
/* done reading, now the book-keeping */
rb->offset += n;
rb->left = left - n;
s->rlayer.packet_length += n;
s->rwstate = SSL_NOTHING;
*readbytes = n;
return 1;
}
/*
* Call this to write data in records of type 'type' It will return <= 0 if
* not all data has been sent or non-blocking IO.
*/
int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
size_t *written)
{
const unsigned char *buf = buf_;
size_t tot;
size_t n, max_send_fragment, split_send_fragment, maxpipes;
#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
size_t nw;
#endif
SSL3_BUFFER *wb = &s->rlayer.wbuf[0];
int i;
size_t tmpwrit;
s->rwstate = SSL_NOTHING;
tot = s->rlayer.wnum;
/*
* ensure that if we end up with a smaller value of data to write out
* than the original len from a write which didn't complete for
* non-blocking I/O and also somehow ended up avoiding the check for
* this in ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as it must never be
* possible to end up with (len-tot) as a large number that will then
* promptly send beyond the end of the users buffer ... so we trap and
* report the error in a way the user will notice
*/
if ((len < s->rlayer.wnum)
|| ((wb->left != 0) && (len < (s->rlayer.wnum + s->rlayer.wpend_tot)))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_LENGTH);
return -1;
}
if (s->early_data_state == SSL_EARLY_DATA_WRITING
&& !early_data_count_ok(s, len, 0, 1)) {
/* SSLfatal() already called */
return -1;
}
s->rlayer.wnum = 0;
/*
* If we are supposed to be sending a KeyUpdate or NewSessionTicket then go
* into init unless we have writes pending - in which case we should finish
* doing that first.
*/
if (wb->left == 0 && (s->key_update != SSL_KEY_UPDATE_NONE
|| s->ext.extra_tickets_expected > 0))
ossl_statem_set_in_init(s, 1);
/*
* When writing early data on the server side we could be "in_init" in
* between receiving the EoED and the CF - but we don't want to handle those
* messages yet.
*/
if (SSL_in_init(s) && !ossl_statem_get_in_handshake(s)
&& s->early_data_state != SSL_EARLY_DATA_UNAUTH_WRITING) {
i = s->handshake_func(s);
/* SSLfatal() already called */
if (i < 0)
return i;
if (i == 0) {
return -1;
}
}
/*
* first check if there is a SSL3_BUFFER still being written out. This
* will happen with non blocking IO
*/
if (wb->left != 0) {
/* SSLfatal() already called if appropriate */
i = ssl3_write_pending(s, type, &buf[tot], s->rlayer.wpend_tot,
&tmpwrit);
if (i <= 0) {
/* XXX should we ssl3_release_write_buffer if i<0? */
s->rlayer.wnum = tot;
return i;
}
tot += tmpwrit; /* this might be last fragment */
}
#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
/*
* Depending on platform multi-block can deliver several *times*
* better performance. Downside is that it has to allocate
* jumbo buffer to accommodate up to 8 records, but the
* compromise is considered worthy.
*/
if (type == SSL3_RT_APPLICATION_DATA
&& len >= 4 * (max_send_fragment = ssl_get_max_send_fragment(s))
&& s->compress == NULL
&& s->msg_callback == NULL
&& !SSL_WRITE_ETM(s)
&& SSL_USE_EXPLICIT_IV(s)
&& BIO_get_ktls_send(s->wbio) == 0
&& (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx))
& EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) != 0) {
unsigned char aad[13];
EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
size_t packlen;
int packleni;
/* minimize address aliasing conflicts */
if ((max_send_fragment & 0xfff) == 0)
max_send_fragment -= 512;
if (tot == 0 || wb->buf == NULL) { /* allocate jumbo buffer */
ssl3_release_write_buffer(s);
packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE,
(int)max_send_fragment, NULL);
if (len >= 8 * max_send_fragment)
packlen *= 8;
else
packlen *= 4;
if (!ssl3_setup_write_buffer(s, 1, packlen)) {
/* SSLfatal() already called */
return -1;
}
} else if (tot == len) { /* done? */
/* free jumbo buffer */
ssl3_release_write_buffer(s);
*written = tot;
return 1;
}
n = (len - tot);
for (;;) {
if (n < 4 * max_send_fragment) {
/* free jumbo buffer */
ssl3_release_write_buffer(s);
break;
}
if (s->s3.alert_dispatch) {
i = s->method->ssl_dispatch_alert(s);
if (i <= 0) {
/* SSLfatal() already called if appropriate */
s->rlayer.wnum = tot;
return i;
}
}
if (n >= 8 * max_send_fragment)
nw = max_send_fragment * (mb_param.interleave = 8);
else
nw = max_send_fragment * (mb_param.interleave = 4);
memcpy(aad, s->rlayer.write_sequence, 8);
aad[8] = type;
aad[9] = (unsigned char)(s->version >> 8);
aad[10] = (unsigned char)(s->version);
aad[11] = 0;
aad[12] = 0;
mb_param.out = NULL;
mb_param.inp = aad;
mb_param.len = nw;
packleni = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
sizeof(mb_param), &mb_param);
packlen = (size_t)packleni;
if (packleni <= 0 || packlen > wb->len) { /* never happens */
/* free jumbo buffer */
ssl3_release_write_buffer(s);
break;
}
mb_param.out = wb->buf;
mb_param.inp = &buf[tot];
mb_param.len = nw;
if (EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
sizeof(mb_param), &mb_param) <= 0)
return -1;
s->rlayer.write_sequence[7] += mb_param.interleave;
if (s->rlayer.write_sequence[7] < mb_param.interleave) {
int j = 6;
while (j >= 0 && (++s->rlayer.write_sequence[j--]) == 0) ;
}
wb->offset = 0;
wb->left = packlen;
s->rlayer.wpend_tot = nw;
s->rlayer.wpend_buf = &buf[tot];
s->rlayer.wpend_type = type;
s->rlayer.wpend_ret = nw;
i = ssl3_write_pending(s, type, &buf[tot], nw, &tmpwrit);
if (i <= 0) {
/* SSLfatal() already called if appropriate */
if (i < 0 && (!s->wbio || !BIO_should_retry(s->wbio))) {
/* free jumbo buffer */
ssl3_release_write_buffer(s);
}
s->rlayer.wnum = tot;
return i;
}
if (tmpwrit == n) {
/* free jumbo buffer */
ssl3_release_write_buffer(s);
*written = tot + tmpwrit;
return 1;
}
n -= tmpwrit;
tot += tmpwrit;
}
} else
#endif /* !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK */
if (tot == len) { /* done? */
if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s))
ssl3_release_write_buffer(s);
*written = tot;
return 1;
}
n = (len - tot);
max_send_fragment = ssl_get_max_send_fragment(s);
split_send_fragment = ssl_get_split_send_fragment(s);
/*
* If max_pipelines is 0 then this means "undefined" and we default to
* 1 pipeline. Similarly if the cipher does not support pipelined
* processing then we also only use 1 pipeline, or if we're not using
* explicit IVs
*/
maxpipes = s->max_pipelines;
if (maxpipes > SSL_MAX_PIPELINES) {
/*
* We should have prevented this when we set max_pipelines so we
* shouldn't get here
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
if (maxpipes == 0
|| s->enc_write_ctx == NULL
|| (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx))
& EVP_CIPH_FLAG_PIPELINE) == 0
|| !SSL_USE_EXPLICIT_IV(s))
maxpipes = 1;
if (max_send_fragment == 0
|| split_send_fragment == 0
|| split_send_fragment > max_send_fragment) {
/*
* We should have prevented this when we set/get the split and max send
* fragments so we shouldn't get here
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
for (;;) {
size_t pipelens[SSL_MAX_PIPELINES], tmppipelen, remain;
size_t numpipes, j;
if (n == 0)
numpipes = 1;
else
numpipes = ((n - 1) / split_send_fragment) + 1;
if (numpipes > maxpipes)
numpipes = maxpipes;
- if (n / numpipes >= max_send_fragment) {
+ if (n / numpipes >= split_send_fragment) {
/*
* We have enough data to completely fill all available
* pipelines
*/
- for (j = 0; j < numpipes; j++) {
- pipelens[j] = max_send_fragment;
- }
+ for (j = 0; j < numpipes; j++)
+ pipelens[j] = split_send_fragment;
} else {
/* We can partially fill all available pipelines */
tmppipelen = n / numpipes;
remain = n % numpipes;
for (j = 0; j < numpipes; j++) {
pipelens[j] = tmppipelen;
if (j < remain)
pipelens[j]++;
}
}
i = do_ssl3_write(s, type, &(buf[tot]), pipelens, numpipes, 0,
&tmpwrit);
if (i <= 0) {
/* SSLfatal() already called if appropriate */
/* XXX should we ssl3_release_write_buffer if i<0? */
s->rlayer.wnum = tot;
return i;
}
if (tmpwrit == n ||
(type == SSL3_RT_APPLICATION_DATA &&
(s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) {
/*
* next chunk of data should get another prepended empty fragment
* in ciphersuites with known-IV weakness:
*/
s->s3.empty_fragment_done = 0;
if (tmpwrit == n
&& (s->mode & SSL_MODE_RELEASE_BUFFERS) != 0
&& !SSL_IS_DTLS(s))
ssl3_release_write_buffer(s);
*written = tot + tmpwrit;
return 1;
}
n -= tmpwrit;
tot += tmpwrit;
}
}
int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
size_t *pipelens, size_t numpipes,
int create_empty_fragment, size_t *written)
{
WPACKET pkt[SSL_MAX_PIPELINES];
SSL3_RECORD wr[SSL_MAX_PIPELINES];
WPACKET *thispkt;
SSL3_RECORD *thiswr;
unsigned char *recordstart;
int i, mac_size, clear = 0;
size_t prefix_len = 0;
int eivlen = 0;
size_t align = 0;
SSL3_BUFFER *wb;
SSL_SESSION *sess;
size_t totlen = 0, len, wpinited = 0;
size_t j;
for (j = 0; j < numpipes; j++)
totlen += pipelens[j];
/*
* first check if there is a SSL3_BUFFER still being written out. This
* will happen with non blocking IO
*/
if (RECORD_LAYER_write_pending(&s->rlayer)) {
/* Calls SSLfatal() as required */
return ssl3_write_pending(s, type, buf, totlen, written);
}
/* If we have an alert to send, lets send it */
if (s->s3.alert_dispatch) {
i = s->method->ssl_dispatch_alert(s);
if (i <= 0) {
/* SSLfatal() already called if appropriate */
return i;
}
/* if it went, fall through and send more stuff */
}
if (s->rlayer.numwpipes < numpipes) {
if (!ssl3_setup_write_buffer(s, numpipes, 0)) {
/* SSLfatal() already called */
return -1;
}
}
if (totlen == 0 && !create_empty_fragment)
return 0;
sess = s->session;
if ((sess == NULL)
|| (s->enc_write_ctx == NULL)
|| (EVP_MD_CTX_get0_md(s->write_hash) == NULL)) {
clear = s->enc_write_ctx ? 0 : 1; /* must be AEAD cipher */
mac_size = 0;
} else {
mac_size = EVP_MD_CTX_get_size(s->write_hash);
if (mac_size < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
/*
* 'create_empty_fragment' is true only when this function calls itself
*/
if (!clear && !create_empty_fragment && !s->s3.empty_fragment_done) {
/*
* countermeasure against known-IV weakness in CBC ciphersuites (see
* http://www.openssl.org/~bodo/tls-cbc.txt)
*/
if (s->s3.need_empty_fragments && type == SSL3_RT_APPLICATION_DATA) {
/*
* recursive function call with 'create_empty_fragment' set; this
* prepares and buffers the data for an empty fragment (these
* 'prefix_len' bytes are sent out later together with the actual
* payload)
*/
size_t tmppipelen = 0;
int ret;
ret = do_ssl3_write(s, type, buf, &tmppipelen, 1, 1, &prefix_len);
if (ret <= 0) {
/* SSLfatal() already called if appropriate */
goto err;
}
if (prefix_len >
(SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD)) {
/* insufficient space */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
s->s3.empty_fragment_done = 1;
}
if (BIO_get_ktls_send(s->wbio)) {
/*
* ktls doesn't modify the buffer, but to avoid a warning we need to
* discard the const qualifier.
* This doesn't leak memory because the buffers have been released when
* switching to ktls.
*/
SSL3_BUFFER_set_buf(&s->rlayer.wbuf[0], (unsigned char *)buf);
SSL3_BUFFER_set_offset(&s->rlayer.wbuf[0], 0);
SSL3_BUFFER_set_app_buffer(&s->rlayer.wbuf[0], 1);
goto wpacket_init_complete;
}
if (create_empty_fragment) {
wb = &s->rlayer.wbuf[0];
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
/*
* extra fragment would be couple of cipher blocks, which would be
* multiple of SSL3_ALIGN_PAYLOAD, so if we want to align the real
* payload, then we can just pretend we simply have two headers.
*/
align = (size_t)SSL3_BUFFER_get_buf(wb) + 2 * SSL3_RT_HEADER_LENGTH;
align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
#endif
SSL3_BUFFER_set_offset(wb, align);
if (!WPACKET_init_static_len(&pkt[0], SSL3_BUFFER_get_buf(wb),
SSL3_BUFFER_get_len(wb), 0)
|| !WPACKET_allocate_bytes(&pkt[0], align, NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
wpinited = 1;
} else if (prefix_len) {
wb = &s->rlayer.wbuf[0];
if (!WPACKET_init_static_len(&pkt[0],
SSL3_BUFFER_get_buf(wb),
SSL3_BUFFER_get_len(wb), 0)
|| !WPACKET_allocate_bytes(&pkt[0], SSL3_BUFFER_get_offset(wb)
+ prefix_len, NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
wpinited = 1;
} else {
for (j = 0; j < numpipes; j++) {
thispkt = &pkt[j];
wb = &s->rlayer.wbuf[j];
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH;
align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
#endif
SSL3_BUFFER_set_offset(wb, align);
if (!WPACKET_init_static_len(thispkt, SSL3_BUFFER_get_buf(wb),
SSL3_BUFFER_get_len(wb), 0)
|| !WPACKET_allocate_bytes(thispkt, align, NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
wpinited++;
}
}
/* Explicit IV length, block ciphers appropriate version flag */
if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s) && !SSL_TREAT_AS_TLS13(s)) {
int mode = EVP_CIPHER_CTX_get_mode(s->enc_write_ctx);
if (mode == EVP_CIPH_CBC_MODE) {
eivlen = EVP_CIPHER_CTX_get_iv_length(s->enc_write_ctx);
if (eivlen < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
goto err;
}
if (eivlen <= 1)
eivlen = 0;
} else if (mode == EVP_CIPH_GCM_MODE) {
/* Need explicit part of IV for GCM mode */
eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
} else if (mode == EVP_CIPH_CCM_MODE) {
eivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
}
}
wpacket_init_complete:
totlen = 0;
/* Clear our SSL3_RECORD structures */
memset(wr, 0, sizeof(wr));
for (j = 0; j < numpipes; j++) {
unsigned int version = (s->version == TLS1_3_VERSION) ? TLS1_2_VERSION
: s->version;
unsigned char *compressdata = NULL;
size_t maxcomplen;
unsigned int rectype;
thispkt = &pkt[j];
thiswr = &wr[j];
/*
* In TLSv1.3, once encrypting, we always use application data for the
* record type
*/
if (SSL_TREAT_AS_TLS13(s)
&& s->enc_write_ctx != NULL
&& (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
|| type != SSL3_RT_ALERT))
rectype = SSL3_RT_APPLICATION_DATA;
else
rectype = type;
SSL3_RECORD_set_type(thiswr, rectype);
/*
* Some servers hang if initial client hello is larger than 256 bytes
* and record version number > TLS 1.0
*/
if (SSL_get_state(s) == TLS_ST_CW_CLNT_HELLO
&& !s->renegotiate
&& TLS1_get_version(s) > TLS1_VERSION
&& s->hello_retry_request == SSL_HRR_NONE)
version = TLS1_VERSION;
SSL3_RECORD_set_rec_version(thiswr, version);
maxcomplen = pipelens[j];
if (s->compress != NULL)
maxcomplen += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
/*
* When using offload kernel will write the header.
* Otherwise write the header now
*/
if (!BIO_get_ktls_send(s->wbio)
&& (!WPACKET_put_bytes_u8(thispkt, rectype)
|| !WPACKET_put_bytes_u16(thispkt, version)
|| !WPACKET_start_sub_packet_u16(thispkt)
|| (eivlen > 0
&& !WPACKET_allocate_bytes(thispkt, eivlen, NULL))
|| (maxcomplen > 0
&& !WPACKET_reserve_bytes(thispkt, maxcomplen,
&compressdata)))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/* lets setup the record stuff. */
SSL3_RECORD_set_data(thiswr, compressdata);
SSL3_RECORD_set_length(thiswr, pipelens[j]);
SSL3_RECORD_set_input(thiswr, (unsigned char *)&buf[totlen]);
totlen += pipelens[j];
/*
* we now 'read' from thiswr->input, thiswr->length bytes into
* thiswr->data
*/
/* first we compress */
if (s->compress != NULL) {
if (!ssl3_do_compress(s, thiswr)
|| !WPACKET_allocate_bytes(thispkt, thiswr->length, NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_COMPRESSION_FAILURE);
goto err;
}
} else {
if (BIO_get_ktls_send(s->wbio)) {
SSL3_RECORD_reset_data(&wr[j]);
} else {
if (!WPACKET_memcpy(thispkt, thiswr->input, thiswr->length)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
SSL3_RECORD_reset_input(&wr[j]);
}
}
if (SSL_TREAT_AS_TLS13(s)
&& !BIO_get_ktls_send(s->wbio)
&& s->enc_write_ctx != NULL
&& (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
|| type != SSL3_RT_ALERT)) {
size_t rlen, max_send_fragment;
if (!WPACKET_put_bytes_u8(thispkt, type)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
SSL3_RECORD_add_length(thiswr, 1);
/* Add TLS1.3 padding */
max_send_fragment = ssl_get_max_send_fragment(s);
rlen = SSL3_RECORD_get_length(thiswr);
if (rlen < max_send_fragment) {
size_t padding = 0;
size_t max_padding = max_send_fragment - rlen;
if (s->record_padding_cb != NULL) {
padding = s->record_padding_cb(s, type, rlen, s->record_padding_arg);
} else if (s->block_padding > 0) {
size_t mask = s->block_padding - 1;
size_t remainder;
/* optimize for power of 2 */
if ((s->block_padding & mask) == 0)
remainder = rlen & mask;
else
remainder = rlen % s->block_padding;
/* don't want to add a block of padding if we don't have to */
if (remainder == 0)
padding = 0;
else
padding = s->block_padding - remainder;
}
if (padding > 0) {
/* do not allow the record to exceed max plaintext length */
if (padding > max_padding)
padding = max_padding;
if (!WPACKET_memset(thispkt, 0, padding)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
ERR_R_INTERNAL_ERROR);
goto err;
}
SSL3_RECORD_add_length(thiswr, padding);
}
}
}
/*
* we should still have the output to thiswr->data and the input from
* wr->input. Length should be thiswr->length. thiswr->data still points
* in the wb->buf
*/
if (!BIO_get_ktls_send(s->wbio) && !SSL_WRITE_ETM(s) && mac_size != 0) {
unsigned char *mac;
if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac)
|| !s->method->ssl3_enc->mac(s, thiswr, mac, 1)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
/*
* Reserve some bytes for any growth that may occur during encryption. If
* we are adding the MAC independently of the cipher algorithm, then the
* max encrypted overhead does not need to include an allocation for that
* MAC
*/
if (!BIO_get_ktls_send(s->wbio)) {
if (!WPACKET_reserve_bytes(thispkt,
SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD
- mac_size, NULL)
/*
* We also need next the amount of bytes written to this
* sub-packet
*/
|| !WPACKET_get_length(thispkt, &len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/* Get a pointer to the start of this record excluding header */
recordstart = WPACKET_get_curr(thispkt) - len;
SSL3_RECORD_set_data(thiswr, recordstart);
SSL3_RECORD_reset_input(thiswr);
SSL3_RECORD_set_length(thiswr, len);
}
}
if (s->statem.enc_write_state == ENC_WRITE_STATE_WRITE_PLAIN_ALERTS) {
/*
* We haven't actually negotiated the version yet, but we're trying to
* send early data - so we need to use the tls13enc function.
*/
if (tls13_enc(s, wr, numpipes, 1, NULL, mac_size) < 1) {
if (!ossl_statem_in_error(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
}
goto err;
}
} else {
if (!BIO_get_ktls_send(s->wbio)) {
if (s->method->ssl3_enc->enc(s, wr, numpipes, 1, NULL,
mac_size) < 1) {
if (!ossl_statem_in_error(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
}
goto err;
}
}
}
for (j = 0; j < numpipes; j++) {
size_t origlen;
thispkt = &pkt[j];
thiswr = &wr[j];
if (BIO_get_ktls_send(s->wbio))
goto mac_done;
/* Allocate bytes for the encryption overhead */
if (!WPACKET_get_length(thispkt, &origlen)
/* Check we allowed enough room for the encryption growth */
|| !ossl_assert(origlen + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD
- mac_size >= thiswr->length)
/* Encryption should never shrink the data! */
|| origlen > thiswr->length
|| (thiswr->length > origlen
&& !WPACKET_allocate_bytes(thispkt,
thiswr->length - origlen,
NULL))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (SSL_WRITE_ETM(s) && mac_size != 0) {
unsigned char *mac;
if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac)
|| !s->method->ssl3_enc->mac(s, thiswr, mac, 1)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
SSL3_RECORD_add_length(thiswr, mac_size);
}
if (!WPACKET_get_length(thispkt, &len)
|| !WPACKET_close(thispkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (s->msg_callback) {
recordstart = WPACKET_get_curr(thispkt) - len
- SSL3_RT_HEADER_LENGTH;
s->msg_callback(1, thiswr->rec_version, SSL3_RT_HEADER, recordstart,
SSL3_RT_HEADER_LENGTH, s,
s->msg_callback_arg);
if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL) {
unsigned char ctype = type;
s->msg_callback(1, thiswr->rec_version, SSL3_RT_INNER_CONTENT_TYPE,
&ctype, 1, s, s->msg_callback_arg);
}
}
if (!WPACKET_finish(thispkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
/* header is added by the kernel when using offload */
SSL3_RECORD_add_length(&wr[j], SSL3_RT_HEADER_LENGTH);
if (create_empty_fragment) {
/*
* we are in a recursive call; just return the length, don't write
* out anything here
*/
if (j > 0) {
/* We should never be pipelining an empty fragment!! */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
*written = SSL3_RECORD_get_length(thiswr);
return 1;
}
mac_done:
/*
* we should now have thiswr->data pointing to the encrypted data, which
* is thiswr->length long
*/
SSL3_RECORD_set_type(thiswr, type); /* not needed but helps for
* debugging */
/* now let's set up wb */
SSL3_BUFFER_set_left(&s->rlayer.wbuf[j],
prefix_len + SSL3_RECORD_get_length(thiswr));
}
/*
* memorize arguments so that ssl3_write_pending can detect bad write
* retries later
*/
s->rlayer.wpend_tot = totlen;
s->rlayer.wpend_buf = buf;
s->rlayer.wpend_type = type;
s->rlayer.wpend_ret = totlen;
/* we now just need to write the buffer */
return ssl3_write_pending(s, type, buf, totlen, written);
err:
for (j = 0; j < wpinited; j++)
WPACKET_cleanup(&pkt[j]);
return -1;
}
/* if s->s3.wbuf.left != 0, we need to call this
*
* Return values are as per SSL_write()
*/
int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len,
size_t *written)
{
int i;
SSL3_BUFFER *wb = s->rlayer.wbuf;
size_t currbuf = 0;
size_t tmpwrit = 0;
if ((s->rlayer.wpend_tot > len)
|| (!(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)
&& (s->rlayer.wpend_buf != buf))
|| (s->rlayer.wpend_type != type)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_WRITE_RETRY);
return -1;
}
for (;;) {
/* Loop until we find a buffer we haven't written out yet */
if (SSL3_BUFFER_get_left(&wb[currbuf]) == 0
&& currbuf < s->rlayer.numwpipes - 1) {
currbuf++;
continue;
}
clear_sys_error();
if (s->wbio != NULL) {
s->rwstate = SSL_WRITING;
/*
* To prevent coalescing of control and data messages,
* such as in buffer_write, we flush the BIO
*/
if (BIO_get_ktls_send(s->wbio) && type != SSL3_RT_APPLICATION_DATA) {
i = BIO_flush(s->wbio);
if (i <= 0)
return i;
BIO_set_ktls_ctrl_msg(s->wbio, type);
}
i = BIO_write(s->wbio, (char *)
&(SSL3_BUFFER_get_buf(&wb[currbuf])
[SSL3_BUFFER_get_offset(&wb[currbuf])]),
(unsigned int)SSL3_BUFFER_get_left(&wb[currbuf]));
if (i >= 0)
tmpwrit = i;
} else {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BIO_NOT_SET);
i = -1;
}
/*
* When an empty fragment is sent on a connection using KTLS,
* it is sent as a write of zero bytes. If this zero byte
* write succeeds, i will be 0 rather than a non-zero value.
* Treat i == 0 as success rather than an error for zero byte
* writes to permit this case.
*/
if (i >= 0 && tmpwrit == SSL3_BUFFER_get_left(&wb[currbuf])) {
SSL3_BUFFER_set_left(&wb[currbuf], 0);
SSL3_BUFFER_add_offset(&wb[currbuf], tmpwrit);
if (currbuf + 1 < s->rlayer.numwpipes)
continue;
s->rwstate = SSL_NOTHING;
*written = s->rlayer.wpend_ret;
return 1;
} else if (i <= 0) {
if (SSL_IS_DTLS(s)) {
/*
* For DTLS, just drop it. That's kind of the whole point in
* using a datagram service
*/
SSL3_BUFFER_set_left(&wb[currbuf], 0);
}
return i;
}
SSL3_BUFFER_add_offset(&wb[currbuf], tmpwrit);
SSL3_BUFFER_sub_left(&wb[currbuf], tmpwrit);
}
}
/*-
* Return up to 'len' payload bytes received in 'type' records.
* 'type' is one of the following:
*
* - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
* - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us)
* - 0 (during a shutdown, no data has to be returned)
*
* If we don't have stored data to work from, read a SSL/TLS record first
* (possibly multiple records if we still don't have anything to return).
*
* This function must handle any surprises the peer may have for us, such as
* Alert records (e.g. close_notify) or renegotiation requests. ChangeCipherSpec
* messages are treated as if they were handshake messages *if* the |recvd_type|
* argument is non NULL.
* Also if record payloads contain fragments too small to process, we store
* them until there is enough for the respective protocol (the record protocol
* may use arbitrary fragmentation and even interleaving):
* Change cipher spec protocol
* just 1 byte needed, no need for keeping anything stored
* Alert protocol
* 2 bytes needed (AlertLevel, AlertDescription)
* Handshake protocol
* 4 bytes needed (HandshakeType, uint24 length) -- we just have
* to detect unexpected Client Hello and Hello Request messages
* here, anything else is handled by higher layers
* Application data protocol
* none of our business
*/
int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
size_t len, int peek, size_t *readbytes)
{
int i, j, ret;
size_t n, curr_rec, num_recs, totalbytes;
SSL3_RECORD *rr;
SSL3_BUFFER *rbuf;
void (*cb) (const SSL *ssl, int type2, int val) = NULL;
int is_tls13 = SSL_IS_TLS13(s);
rbuf = &s->rlayer.rbuf;
if (!SSL3_BUFFER_is_initialised(rbuf)) {
/* Not initialized yet */
if (!ssl3_setup_read_buffer(s)) {
/* SSLfatal() already called */
return -1;
}
}
if ((type && (type != SSL3_RT_APPLICATION_DATA)
&& (type != SSL3_RT_HANDSHAKE)) || (peek
&& (type !=
SSL3_RT_APPLICATION_DATA))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
if ((type == SSL3_RT_HANDSHAKE) && (s->rlayer.handshake_fragment_len > 0))
/* (partially) satisfy request from storage */
{
unsigned char *src = s->rlayer.handshake_fragment;
unsigned char *dst = buf;
unsigned int k;
/* peek == 0 */
n = 0;
while ((len > 0) && (s->rlayer.handshake_fragment_len > 0)) {
*dst++ = *src++;
len--;
s->rlayer.handshake_fragment_len--;
n++;
}
/* move any remaining fragment bytes: */
for (k = 0; k < s->rlayer.handshake_fragment_len; k++)
s->rlayer.handshake_fragment[k] = *src++;
if (recvd_type != NULL)
*recvd_type = SSL3_RT_HANDSHAKE;
*readbytes = n;
return 1;
}
/*
* Now s->rlayer.handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE.
*/
if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) {
/* type == SSL3_RT_APPLICATION_DATA */
i = s->handshake_func(s);
/* SSLfatal() already called */
if (i < 0)
return i;
if (i == 0)
return -1;
}
start:
s->rwstate = SSL_NOTHING;
/*-
* For each record 'i' up to |num_recs]
* rr[i].type - is the type of record
* rr[i].data, - data
* rr[i].off, - offset into 'data' for next read
* rr[i].length, - number of bytes.
*/
rr = s->rlayer.rrec;
num_recs = RECORD_LAYER_get_numrpipes(&s->rlayer);
do {
/* get new records if necessary */
if (num_recs == 0) {
ret = ssl3_get_record(s);
if (ret <= 0) {
/* SSLfatal() already called if appropriate */
return ret;
}
num_recs = RECORD_LAYER_get_numrpipes(&s->rlayer);
if (num_recs == 0) {
/* Shouldn't happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
}
/* Skip over any records we have already read */
for (curr_rec = 0;
curr_rec < num_recs && SSL3_RECORD_is_read(&rr[curr_rec]);
curr_rec++) ;
if (curr_rec == num_recs) {
RECORD_LAYER_set_numrpipes(&s->rlayer, 0);
num_recs = 0;
curr_rec = 0;
}
} while (num_recs == 0);
rr = &rr[curr_rec];
if (s->rlayer.handshake_fragment_len > 0
&& SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE
&& SSL_IS_TLS13(s)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA);
return -1;
}
/*
* Reset the count of consecutive warning alerts if we've got a non-empty
* record that isn't an alert.
*/
if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT
&& SSL3_RECORD_get_length(rr) != 0)
s->rlayer.alert_count = 0;
/* we now have a packet which can be read and processed */
if (s->s3.change_cipher_spec /* set when we receive ChangeCipherSpec,
* reset by ssl3_get_finished */
&& (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
return -1;
}
/*
* If the other end has shut down, throw anything we read away (even in
* 'peek' mode)
*/
if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
SSL3_RECORD_set_length(rr, 0);
s->rwstate = SSL_NOTHING;
return 0;
}
if (type == SSL3_RECORD_get_type(rr)
|| (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
&& type == SSL3_RT_HANDSHAKE && recvd_type != NULL
&& !is_tls13)) {
/*
* SSL3_RT_APPLICATION_DATA or
* SSL3_RT_HANDSHAKE or
* SSL3_RT_CHANGE_CIPHER_SPEC
*/
/*
* make sure that we are not getting application data when we are
* doing a handshake for the first time
*/
if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
(s->enc_read_ctx == NULL)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_APP_DATA_IN_HANDSHAKE);
return -1;
}
if (type == SSL3_RT_HANDSHAKE
&& SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC
&& s->rlayer.handshake_fragment_len > 0) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_CCS_RECEIVED_EARLY);
return -1;
}
if (recvd_type != NULL)
*recvd_type = SSL3_RECORD_get_type(rr);
if (len == 0) {
/*
* Mark a zero length record as read. This ensures multiple calls to
* SSL_read() with a zero length buffer will eventually cause
* SSL_pending() to report data as being available.
*/
if (SSL3_RECORD_get_length(rr) == 0)
SSL3_RECORD_set_read(rr);
return 0;
}
totalbytes = 0;
do {
if (len - totalbytes > SSL3_RECORD_get_length(rr))
n = SSL3_RECORD_get_length(rr);
else
n = len - totalbytes;
memcpy(buf, &(rr->data[rr->off]), n);
buf += n;
if (peek) {
/* Mark any zero length record as consumed CVE-2016-6305 */
if (SSL3_RECORD_get_length(rr) == 0)
SSL3_RECORD_set_read(rr);
} else {
if (s->options & SSL_OP_CLEANSE_PLAINTEXT)
OPENSSL_cleanse(&(rr->data[rr->off]), n);
SSL3_RECORD_sub_length(rr, n);
SSL3_RECORD_add_off(rr, n);
if (SSL3_RECORD_get_length(rr) == 0) {
s->rlayer.rstate = SSL_ST_READ_HEADER;
SSL3_RECORD_set_off(rr, 0);
SSL3_RECORD_set_read(rr);
}
}
if (SSL3_RECORD_get_length(rr) == 0
|| (peek && n == SSL3_RECORD_get_length(rr))) {
curr_rec++;
rr++;
}
totalbytes += n;
} while (type == SSL3_RT_APPLICATION_DATA && curr_rec < num_recs
&& totalbytes < len);
if (totalbytes == 0) {
/* We must have read empty records. Get more data */
goto start;
}
if (!peek && curr_rec == num_recs
&& (s->mode & SSL_MODE_RELEASE_BUFFERS)
&& SSL3_BUFFER_get_left(rbuf) == 0)
ssl3_release_read_buffer(s);
*readbytes = totalbytes;
return 1;
}
/*
* If we get here, then type != rr->type; if we have a handshake message,
* then it was unexpected (Hello Request or Client Hello) or invalid (we
* were actually expecting a CCS).
*/
/*
* Lets just double check that we've not got an SSLv2 record
*/
if (rr->rec_version == SSL2_VERSION) {
/*
* Should never happen. ssl3_get_record() should only give us an SSLv2
* record back if this is the first packet and we are looking for an
* initial ClientHello. Therefore |type| should always be equal to
* |rr->type|. If not then something has gone horribly wrong
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
if (s->method->version == TLS_ANY_VERSION
&& (s->server || rr->type != SSL3_RT_ALERT)) {
/*
* If we've got this far and still haven't decided on what version
* we're using then this must be a client side alert we're dealing
* with. We shouldn't be receiving anything other than a ClientHello
* if we are a server.
*/
s->version = rr->rec_version;
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
return -1;
}
/*-
* s->rlayer.handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE;
* (Possibly rr is 'empty' now, i.e. rr->length may be 0.)
*/
if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) {
unsigned int alert_level, alert_descr;
unsigned char *alert_bytes = SSL3_RECORD_get_data(rr)
+ SSL3_RECORD_get_off(rr);
PACKET alert;
if (!PACKET_buf_init(&alert, alert_bytes, SSL3_RECORD_get_length(rr))
|| !PACKET_get_1(&alert, &alert_level)
|| !PACKET_get_1(&alert, &alert_descr)
|| PACKET_remaining(&alert) != 0) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_INVALID_ALERT);
return -1;
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_bytes, 2, s,
s->msg_callback_arg);
if (s->info_callback != NULL)
cb = s->info_callback;
else if (s->ctx->info_callback != NULL)
cb = s->ctx->info_callback;
if (cb != NULL) {
j = (alert_level << 8) | alert_descr;
cb(s, SSL_CB_READ_ALERT, j);
}
if (alert_level == SSL3_AL_WARNING
|| (is_tls13 && alert_descr == SSL_AD_USER_CANCELLED)) {
s->s3.warn_alert = alert_descr;
SSL3_RECORD_set_read(rr);
s->rlayer.alert_count++;
if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_TOO_MANY_WARN_ALERTS);
return -1;
}
}
/*
* Apart from close_notify the only other warning alert in TLSv1.3
* is user_cancelled - which we just ignore.
*/
if (is_tls13 && alert_descr == SSL_AD_USER_CANCELLED) {
goto start;
} else if (alert_descr == SSL_AD_CLOSE_NOTIFY
&& (is_tls13 || alert_level == SSL3_AL_WARNING)) {
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
return 0;
} else if (alert_level == SSL3_AL_FATAL || is_tls13) {
s->rwstate = SSL_NOTHING;
s->s3.fatal_alert = alert_descr;
SSLfatal_data(s, SSL_AD_NO_ALERT,
SSL_AD_REASON_OFFSET + alert_descr,
"SSL alert number %d", alert_descr);
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
SSL3_RECORD_set_read(rr);
SSL_CTX_remove_session(s->session_ctx, s->session);
return 0;
} else if (alert_descr == SSL_AD_NO_RENEGOTIATION) {
/*
* This is a warning but we receive it if we requested
* renegotiation and the peer denied it. Terminate with a fatal
* alert because if application tried to renegotiate it
* presumably had a good reason and expects it to succeed. In
* future we might have a renegotiation where we don't care if
* the peer refused it where we carry on.
*/
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_NO_RENEGOTIATION);
return -1;
} else if (alert_level == SSL3_AL_WARNING) {
/* We ignore any other warning alert in TLSv1.2 and below */
goto start;
}
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_UNKNOWN_ALERT_TYPE);
return -1;
}
if ((s->shutdown & SSL_SENT_SHUTDOWN) != 0) {
if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) {
BIO *rbio;
/*
* We ignore any handshake messages sent to us unless they are
* TLSv1.3 in which case we want to process them. For all other
* handshake messages we can't do anything reasonable with them
* because we are unable to write any response due to having already
* sent close_notify.
*/
if (!SSL_IS_TLS13(s)) {
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
if ((s->mode & SSL_MODE_AUTO_RETRY) != 0)
goto start;
s->rwstate = SSL_READING;
rbio = SSL_get_rbio(s);
BIO_clear_retry_flags(rbio);
BIO_set_retry_read(rbio);
return -1;
}
} else {
/*
* The peer is continuing to send application data, but we have
* already sent close_notify. If this was expected we should have
* been called via SSL_read() and this would have been handled
* above.
* No alert sent because we already sent close_notify
*/
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
SSLfatal(s, SSL_AD_NO_ALERT,
SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY);
return -1;
}
}
/*
* For handshake data we have 'fragment' storage, so fill that so that we
* can process the header at a fixed place. This is done after the
* "SHUTDOWN" code above to avoid filling the fragment storage with data
* that we're just going to discard.
*/
if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) {
size_t dest_maxlen = sizeof(s->rlayer.handshake_fragment);
unsigned char *dest = s->rlayer.handshake_fragment;
size_t *dest_len = &s->rlayer.handshake_fragment_len;
n = dest_maxlen - *dest_len; /* available space in 'dest' */
if (SSL3_RECORD_get_length(rr) < n)
n = SSL3_RECORD_get_length(rr); /* available bytes */
/* now move 'n' bytes: */
memcpy(dest + *dest_len,
SSL3_RECORD_get_data(rr) + SSL3_RECORD_get_off(rr), n);
SSL3_RECORD_add_off(rr, n);
SSL3_RECORD_sub_length(rr, n);
*dest_len += n;
if (SSL3_RECORD_get_length(rr) == 0)
SSL3_RECORD_set_read(rr);
if (*dest_len < dest_maxlen)
goto start; /* fragment was too small */
}
if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_CCS_RECEIVED_EARLY);
return -1;
}
/*
* Unexpected handshake message (ClientHello, NewSessionTicket (TLS1.3) or
* protocol violation)
*/
if ((s->rlayer.handshake_fragment_len >= 4)
&& !ossl_statem_get_in_handshake(s)) {
int ined = (s->early_data_state == SSL_EARLY_DATA_READING);
/* We found handshake data, so we're going back into init */
ossl_statem_set_in_init(s, 1);
i = s->handshake_func(s);
/* SSLfatal() already called if appropriate */
if (i < 0)
return i;
if (i == 0) {
return -1;
}
/*
* If we were actually trying to read early data and we found a
* handshake message, then we don't want to continue to try and read
* the application data any more. It won't be "early" now.
*/
if (ined)
return -1;
if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
if (SSL3_BUFFER_get_left(rbuf) == 0) {
/* no read-ahead left? */
BIO *bio;
/*
* In the case where we try to read application data, but we
* trigger an SSL handshake, we return -1 with the retry
* option set. Otherwise renegotiation may cause nasty
* problems in the blocking world
*/
s->rwstate = SSL_READING;
bio = SSL_get_rbio(s);
BIO_clear_retry_flags(bio);
BIO_set_retry_read(bio);
return -1;
}
}
goto start;
}
switch (SSL3_RECORD_get_type(rr)) {
default:
/*
* TLS 1.0 and 1.1 say you SHOULD ignore unrecognised record types, but
* TLS 1.2 says you MUST send an unexpected message alert. We use the
* TLS 1.2 behaviour for all protocol versions to prevent issues where
* no progress is being made and the peer continually sends unrecognised
* record types, using up resources processing them.
*/
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_RECORD);
return -1;
case SSL3_RT_CHANGE_CIPHER_SPEC:
case SSL3_RT_ALERT:
case SSL3_RT_HANDSHAKE:
/*
* we already handled all of these, with the possible exception of
* SSL3_RT_HANDSHAKE when ossl_statem_get_in_handshake(s) is true, but
* that should not happen when type != rr->type
*/
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, ERR_R_INTERNAL_ERROR);
return -1;
case SSL3_RT_APPLICATION_DATA:
/*
* At this point, we were expecting handshake data, but have
* application data. If the library was running inside ssl3_read()
* (i.e. in_read_app_data is set) and it makes sense to read
* application data at this point (session renegotiation not yet
* started), we will indulge it.
*/
if (ossl_statem_app_data_allowed(s)) {
s->s3.in_read_app_data = 2;
return -1;
} else if (ossl_statem_skip_early_data(s)) {
/*
* This can happen after a client sends a CH followed by early_data,
* but the server responds with a HelloRetryRequest. The server
* reads the next record from the client expecting to find a
* plaintext ClientHello but gets a record which appears to be
* application data. The trial decrypt "works" because null
* decryption was applied. We just skip it and move on to the next
* record.
*/
if (!early_data_count_ok(s, rr->length,
EARLY_DATA_CIPHERTEXT_OVERHEAD, 0)) {
/* SSLfatal() already called */
return -1;
}
SSL3_RECORD_set_read(rr);
goto start;
} else {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_RECORD);
return -1;
}
}
}
void ssl3_record_sequence_update(unsigned char *seq)
{
int i;
for (i = 7; i >= 0; i--) {
++seq[i];
if (seq[i] != 0)
break;
}
}
/*
* Returns true if the current rrec was sent in SSLv2 backwards compatible
* format and false otherwise.
*/
int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl)
{
return SSL3_RECORD_is_sslv2_record(&rl->rrec[0]);
}
/*
* Returns the length in bytes of the current rrec
*/
size_t RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl)
{
return SSL3_RECORD_get_length(&rl->rrec[0]);
}
diff --git a/ssl/record/ssl3_buffer.c b/ssl/record/ssl3_buffer.c
index f631829ef646..97b0c26ced81 100644
--- a/ssl/record/ssl3_buffer.c
+++ b/ssl/record/ssl3_buffer.c
@@ -1,190 +1,195 @@
/*
* 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 "../ssl_local.h"
#include "record_local.h"
void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, size_t n)
{
if (d != NULL)
memcpy(b->buf, d, n);
b->left = n;
b->offset = 0;
}
/*
* Clear the contents of an SSL3_BUFFER but retain any memory allocated. Also
* retains the default_len setting
*/
void SSL3_BUFFER_clear(SSL3_BUFFER *b)
{
b->offset = 0;
b->left = 0;
}
void SSL3_BUFFER_release(SSL3_BUFFER *b)
{
OPENSSL_free(b->buf);
b->buf = NULL;
}
int ssl3_setup_read_buffer(SSL *s)
{
unsigned char *p;
size_t len, align = 0, headerlen;
SSL3_BUFFER *b;
b = RECORD_LAYER_get_rbuf(&s->rlayer);
if (SSL_IS_DTLS(s))
headerlen = DTLS1_RT_HEADER_LENGTH;
else
headerlen = SSL3_RT_HEADER_LENGTH;
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
#endif
if (b->buf == NULL) {
len = SSL3_RT_MAX_PLAIN_LENGTH
+ SSL3_RT_MAX_ENCRYPTED_OVERHEAD + headerlen + align;
#ifndef OPENSSL_NO_COMP
if (ssl_allow_compression(s))
len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
#endif
+
+ /* Ensure our buffer is large enough to support all our pipelines */
+ if (s->max_pipelines > 1)
+ len *= s->max_pipelines;
+
if (b->default_len > len)
len = b->default_len;
if ((p = OPENSSL_malloc(len)) == NULL) {
/*
* We've got a malloc failure, and we're still initialising buffers.
* We assume we're so doomed that we won't even be able to send an
* alert.
*/
SSLfatal(s, SSL_AD_NO_ALERT, ERR_R_MALLOC_FAILURE);
return 0;
}
b->buf = p;
b->len = len;
}
return 1;
}
int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len)
{
unsigned char *p;
size_t align = 0, headerlen;
SSL3_BUFFER *wb;
size_t currpipe;
s->rlayer.numwpipes = numwpipes;
if (len == 0) {
if (SSL_IS_DTLS(s))
headerlen = DTLS1_RT_HEADER_LENGTH + 1;
else
headerlen = SSL3_RT_HEADER_LENGTH;
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
align = SSL3_ALIGN_PAYLOAD - 1;
#endif
len = ssl_get_max_send_fragment(s)
+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align
+ SSL_RT_MAX_CIPHER_BLOCK_SIZE /* Explicit IV allowance */;
#ifndef OPENSSL_NO_COMP
if (ssl_allow_compression(s))
len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
#endif
/*
* We don't need to add an allowance for eivlen here since empty
* fragments only occur when we don't have an explicit IV
*/
if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
}
wb = RECORD_LAYER_get_wbuf(&s->rlayer);
for (currpipe = 0; currpipe < numwpipes; currpipe++) {
SSL3_BUFFER *thiswb = &wb[currpipe];
if (thiswb->len != len) {
OPENSSL_free(thiswb->buf);
thiswb->buf = NULL; /* force reallocation */
}
if (thiswb->buf == NULL) {
if (s->wbio == NULL || !BIO_get_ktls_send(s->wbio)) {
p = OPENSSL_malloc(len);
if (p == NULL) {
s->rlayer.numwpipes = currpipe;
/*
* We've got a malloc failure, and we're still initialising
* buffers. We assume we're so doomed that we won't even be able
* to send an alert.
*/
SSLfatal(s, SSL_AD_NO_ALERT, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
p = NULL;
}
memset(thiswb, 0, sizeof(SSL3_BUFFER));
thiswb->buf = p;
thiswb->len = len;
}
}
return 1;
}
int ssl3_setup_buffers(SSL *s)
{
if (!ssl3_setup_read_buffer(s)) {
/* SSLfatal() already called */
return 0;
}
if (!ssl3_setup_write_buffer(s, 1, 0)) {
/* SSLfatal() already called */
return 0;
}
return 1;
}
int ssl3_release_write_buffer(SSL *s)
{
SSL3_BUFFER *wb;
size_t pipes;
pipes = s->rlayer.numwpipes;
while (pipes > 0) {
wb = &RECORD_LAYER_get_wbuf(&s->rlayer)[pipes - 1];
if (SSL3_BUFFER_is_app_buffer(wb))
SSL3_BUFFER_set_app_buffer(wb, 0);
else
OPENSSL_free(wb->buf);
wb->buf = NULL;
pipes--;
}
s->rlayer.numwpipes = 0;
return 1;
}
int ssl3_release_read_buffer(SSL *s)
{
SSL3_BUFFER *b;
b = RECORD_LAYER_get_rbuf(&s->rlayer);
if (s->options & SSL_OP_CLEANSE_PLAINTEXT)
OPENSSL_cleanse(b->buf, b->len);
OPENSSL_free(b->buf);
b->buf = NULL;
return 1;
}
diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c
index 1867f001179f..3c0b1323a459 100644
--- a/ssl/record/ssl3_record.c
+++ b/ssl/record/ssl3_record.c
@@ -1,1923 +1,1933 @@
/*
* 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 "../ssl_local.h"
#include <openssl/trace.h>
#include <openssl/rand.h>
#include <openssl/core_names.h>
#include "record_local.h"
#include "internal/cryptlib.h"
static const unsigned char ssl3_pad_1[48] = {
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
};
static const unsigned char ssl3_pad_2[48] = {
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
};
/*
* Clear the contents of an SSL3_RECORD but retain any memory allocated
*/
void SSL3_RECORD_clear(SSL3_RECORD *r, size_t num_recs)
{
unsigned char *comp;
size_t i;
for (i = 0; i < num_recs; i++) {
comp = r[i].comp;
memset(&r[i], 0, sizeof(*r));
r[i].comp = comp;
}
}
void SSL3_RECORD_release(SSL3_RECORD *r, size_t num_recs)
{
size_t i;
for (i = 0; i < num_recs; i++) {
OPENSSL_free(r[i].comp);
r[i].comp = NULL;
}
}
void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num)
{
memcpy(r->seq_num, seq_num, SEQ_NUM_SIZE);
}
/*
* Peeks ahead into "read_ahead" data to see if we have a whole record waiting
* for us in the buffer.
*/
static int ssl3_record_app_data_waiting(SSL *s)
{
SSL3_BUFFER *rbuf;
size_t left, len;
unsigned char *p;
rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
p = SSL3_BUFFER_get_buf(rbuf);
if (p == NULL)
return 0;
left = SSL3_BUFFER_get_left(rbuf);
if (left < SSL3_RT_HEADER_LENGTH)
return 0;
p += SSL3_BUFFER_get_offset(rbuf);
/*
* We only check the type and record length, we will sanity check version
* etc later
*/
if (*p != SSL3_RT_APPLICATION_DATA)
return 0;
p += 3;
n2s(p, len);
if (left < SSL3_RT_HEADER_LENGTH + len)
return 0;
return 1;
}
int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send)
{
uint32_t max_early_data;
SSL_SESSION *sess = s->session;
/*
* If we are a client then we always use the max_early_data from the
* session/psksession. Otherwise we go with the lowest out of the max early
* data set in the session and the configured max_early_data.
*/
if (!s->server && sess->ext.max_early_data == 0) {
if (!ossl_assert(s->psksession != NULL
&& s->psksession->ext.max_early_data > 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
sess = s->psksession;
}
if (!s->server)
max_early_data = sess->ext.max_early_data;
else if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED)
max_early_data = s->recv_max_early_data;
else
max_early_data = s->recv_max_early_data < sess->ext.max_early_data
? s->recv_max_early_data : sess->ext.max_early_data;
if (max_early_data == 0) {
SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_TOO_MUCH_EARLY_DATA);
return 0;
}
/* If we are dealing with ciphertext we need to allow for the overhead */
max_early_data += overhead;
if (s->early_data_count + length > max_early_data) {
SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_TOO_MUCH_EARLY_DATA);
return 0;
}
s->early_data_count += length;
return 1;
}
/*
* MAX_EMPTY_RECORDS defines the number of consecutive, empty records that
* will be processed per call to ssl3_get_record. Without this limit an
* attacker could send empty records at a faster rate than we can process and
* cause ssl3_get_record to loop forever.
*/
#define MAX_EMPTY_RECORDS 32
#define SSL2_RT_HEADER_LENGTH 2
/*-
* Call this to get new input records.
* It will return <= 0 if more data is needed, normally due to an error
* or non-blocking IO.
* When it finishes, |numrpipes| records have been decoded. For each record 'i':
* rr[i].type - is the type of record
* rr[i].data, - data
* rr[i].length, - number of bytes
* Multiple records will only be returned if the record types are all
* SSL3_RT_APPLICATION_DATA. The number of records returned will always be <=
* |max_pipelines|
*/
/* used only by ssl3_read_bytes */
int ssl3_get_record(SSL *s)
{
int enc_err, rret;
int i;
size_t more, n;
SSL3_RECORD *rr, *thisrr;
SSL3_BUFFER *rbuf;
SSL_SESSION *sess;
unsigned char *p;
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int version;
size_t mac_size = 0;
int imac_size;
size_t num_recs = 0, max_recs, j;
PACKET pkt, sslv2pkt;
int is_ktls_left;
SSL_MAC_BUF *macbufs = NULL;
int ret = -1;
rr = RECORD_LAYER_get_rrec(&s->rlayer);
rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
is_ktls_left = (SSL3_BUFFER_get_left(rbuf) > 0);
max_recs = s->max_pipelines;
if (max_recs == 0)
max_recs = 1;
sess = s->session;
do {
thisrr = &rr[num_recs];
/* check if we have the header */
if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
(RECORD_LAYER_get_packet_length(&s->rlayer)
< SSL3_RT_HEADER_LENGTH)) {
size_t sslv2len;
unsigned int type;
rret = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH,
SSL3_BUFFER_get_len(rbuf), 0,
num_recs == 0 ? 1 : 0, &n);
if (rret <= 0) {
#ifndef OPENSSL_NO_KTLS
if (!BIO_get_ktls_recv(s->rbio) || rret == 0)
return rret; /* error or non-blocking */
switch (errno) {
case EBADMSG:
SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
break;
case EMSGSIZE:
SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_PACKET_LENGTH_TOO_LONG);
break;
case EINVAL:
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_R_WRONG_VERSION_NUMBER);
break;
default:
break;
}
#endif
return rret;
}
RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
p = RECORD_LAYER_get_packet(&s->rlayer);
if (!PACKET_buf_init(&pkt, RECORD_LAYER_get_packet(&s->rlayer),
RECORD_LAYER_get_packet_length(&s->rlayer))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
sslv2pkt = pkt;
if (!PACKET_get_net_2_len(&sslv2pkt, &sslv2len)
|| !PACKET_get_1(&sslv2pkt, &type)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
/*
* The first record received by the server may be a V2ClientHello.
*/
if (s->server && RECORD_LAYER_is_first_record(&s->rlayer)
&& (sslv2len & 0x8000) != 0
&& (type == SSL2_MT_CLIENT_HELLO)) {
/*
* SSLv2 style record
*
* |num_recs| here will actually always be 0 because
* |num_recs > 0| only ever occurs when we are processing
* multiple app data records - which we know isn't the case here
* because it is an SSLv2ClientHello. We keep it using
* |num_recs| for the sake of consistency
*/
thisrr->type = SSL3_RT_HANDSHAKE;
thisrr->rec_version = SSL2_VERSION;
thisrr->length = sslv2len & 0x7fff;
if (thisrr->length > SSL3_BUFFER_get_len(rbuf)
- SSL2_RT_HEADER_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_PACKET_LENGTH_TOO_LONG);
return -1;
}
if (thisrr->length < MIN_SSL2_RECORD_LEN) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
return -1;
}
} else {
/* SSLv3+ style record */
/* Pull apart the header into the SSL3_RECORD */
if (!PACKET_get_1(&pkt, &type)
|| !PACKET_get_net_2(&pkt, &version)
|| !PACKET_get_net_2_len(&pkt, &thisrr->length)) {
if (s->msg_callback)
s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s,
s->msg_callback_arg);
SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
thisrr->type = type;
thisrr->rec_version = version;
if (s->msg_callback)
s->msg_callback(0, version, SSL3_RT_HEADER, p, 5, s,
s->msg_callback_arg);
/*
* Lets check version. In TLSv1.3 we only check this field
* when encryption is occurring (see later check). For the
* ServerHello after an HRR we haven't actually selected TLSv1.3
* yet, but we still treat it as TLSv1.3, so we must check for
* that explicitly
*/
if (!s->first_packet && !SSL_IS_TLS13(s)
&& s->hello_retry_request != SSL_HRR_PENDING
&& version != (unsigned int)s->version) {
if ((s->version & 0xFF00) == (version & 0xFF00)
&& !s->enc_write_ctx && !s->write_hash) {
if (thisrr->type == SSL3_RT_ALERT) {
/*
* The record is using an incorrect version number,
* but what we've got appears to be an alert. We
* haven't read the body yet to check whether its a
* fatal or not - but chances are it is. We probably
* shouldn't send a fatal alert back. We'll just
* end.
*/
SSLfatal(s, SSL_AD_NO_ALERT,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
/*
* Send back error using their minor version number :-)
*/
s->version = (unsigned short)version;
}
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
if ((version >> 8) != SSL3_VERSION_MAJOR) {
if (RECORD_LAYER_is_first_record(&s->rlayer)) {
/* Go back to start of packet, look at the five bytes
* that we have. */
p = RECORD_LAYER_get_packet(&s->rlayer);
if (strncmp((char *)p, "GET ", 4) == 0 ||
strncmp((char *)p, "POST ", 5) == 0 ||
strncmp((char *)p, "HEAD ", 5) == 0 ||
strncmp((char *)p, "PUT ", 4) == 0) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_R_HTTP_REQUEST);
return -1;
} else if (strncmp((char *)p, "CONNE", 5) == 0) {
SSLfatal(s, SSL_AD_NO_ALERT,
SSL_R_HTTPS_PROXY_REQUEST);
return -1;
}
/* Doesn't look like TLS - don't send an alert */
SSLfatal(s, SSL_AD_NO_ALERT,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
} else {
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
}
if (SSL_IS_TLS13(s) && s->enc_read_ctx != NULL) {
if (thisrr->type != SSL3_RT_APPLICATION_DATA
&& (thisrr->type != SSL3_RT_CHANGE_CIPHER_SPEC
|| !SSL_IS_FIRST_HANDSHAKE(s))
&& (thisrr->type != SSL3_RT_ALERT
|| s->statem.enc_read_state
!= ENC_READ_STATE_ALLOW_PLAIN_ALERTS)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_BAD_RECORD_TYPE);
return -1;
}
if (thisrr->rec_version != TLS1_2_VERSION) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
}
if (thisrr->length >
SSL3_BUFFER_get_len(rbuf) - SSL3_RT_HEADER_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_PACKET_LENGTH_TOO_LONG);
return -1;
}
}
/* now s->rlayer.rstate == SSL_ST_READ_BODY */
}
if (SSL_IS_TLS13(s)) {
if (thisrr->length > SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
return -1;
}
} else {
size_t len = SSL3_RT_MAX_ENCRYPTED_LENGTH;
#ifndef OPENSSL_NO_COMP
/*
* If OPENSSL_NO_COMP is defined then SSL3_RT_MAX_ENCRYPTED_LENGTH
* does not include the compression overhead anyway.
*/
if (s->expand == NULL)
len -= SSL3_RT_MAX_COMPRESSED_OVERHEAD;
#endif
/* KTLS may use all of the buffer */
if (BIO_get_ktls_recv(s->rbio) && !is_ktls_left)
len = SSL3_BUFFER_get_left(rbuf);
if (thisrr->length > len) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
return -1;
}
}
/*
* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data.
* Calculate how much more data we need to read for the rest of the
* record
*/
if (thisrr->rec_version == SSL2_VERSION) {
more = thisrr->length + SSL2_RT_HEADER_LENGTH
- SSL3_RT_HEADER_LENGTH;
} else {
more = thisrr->length;
}
if (more > 0) {
/* now s->rlayer.packet_length == SSL3_RT_HEADER_LENGTH */
rret = ssl3_read_n(s, more, more, 1, 0, &n);
if (rret <= 0)
return rret; /* error or non-blocking io */
}
/* set state for later operations */
RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER);
/*
* At this point, s->rlayer.packet_length == SSL3_RT_HEADER_LENGTH
* + thisrr->length, or s->rlayer.packet_length == SSL2_RT_HEADER_LENGTH
* + thisrr->length and we have that many bytes in s->rlayer.packet
*/
if (thisrr->rec_version == SSL2_VERSION) {
thisrr->input =
&(RECORD_LAYER_get_packet(&s->rlayer)[SSL2_RT_HEADER_LENGTH]);
} else {
thisrr->input =
&(RECORD_LAYER_get_packet(&s->rlayer)[SSL3_RT_HEADER_LENGTH]);
}
/*
* ok, we can now read from 's->rlayer.packet' data into 'thisrr'.
* thisrr->input points at thisrr->length bytes, which need to be copied
* into thisrr->data by either the decryption or by the decompression.
* When the data is 'copied' into the thisrr->data buffer,
* thisrr->input will be updated to point at the new buffer
*/
/*
* We now have - encrypted [ MAC [ compressed [ plain ] ] ]
* thisrr->length bytes of encrypted compressed stuff.
*/
/* decrypt in place in 'thisrr->input' */
thisrr->data = thisrr->input;
thisrr->orig_len = thisrr->length;
/* Mark this record as not read by upper layers yet */
thisrr->read = 0;
num_recs++;
/* we have pulled in a full packet so zero things */
RECORD_LAYER_reset_packet_length(&s->rlayer);
RECORD_LAYER_clear_first_record(&s->rlayer);
} while (num_recs < max_recs
&& thisrr->type == SSL3_RT_APPLICATION_DATA
&& SSL_USE_EXPLICIT_IV(s)
&& s->enc_read_ctx != NULL
&& (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(s->enc_read_ctx))
& EVP_CIPH_FLAG_PIPELINE) != 0
&& ssl3_record_app_data_waiting(s));
if (num_recs == 1
&& thisrr->type == SSL3_RT_CHANGE_CIPHER_SPEC
&& (SSL_IS_TLS13(s) || s->hello_retry_request != SSL_HRR_NONE)
&& SSL_IS_FIRST_HANDSHAKE(s)) {
/*
* CCS messages must be exactly 1 byte long, containing the value 0x01
*/
if (thisrr->length != 1 || thisrr->data[0] != 0x01) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_INVALID_CCS_MESSAGE);
return -1;
}
/*
* CCS messages are ignored in TLSv1.3. We treat it like an empty
* handshake record
*/
thisrr->type = SSL3_RT_HANDSHAKE;
RECORD_LAYER_inc_empty_record_count(&s->rlayer);
if (RECORD_LAYER_get_empty_record_count(&s->rlayer)
> MAX_EMPTY_RECORDS) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_UNEXPECTED_CCS_MESSAGE);
return -1;
}
thisrr->read = 1;
RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
return 1;
}
/*
* KTLS reads full records. If there is any data left,
* then it is from before enabling ktls
*/
if (BIO_get_ktls_recv(s->rbio) && !is_ktls_left)
goto skip_decryption;
if (s->read_hash != NULL) {
const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(s->read_hash);
if (tmpmd != NULL) {
imac_size = EVP_MD_get_size(tmpmd);
if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
return -1;
}
mac_size = (size_t)imac_size;
}
}
/*
* If in encrypt-then-mac mode calculate mac from encrypted record. All
* the details below are public so no timing details can leak.
*/
if (SSL_READ_ETM(s) && s->read_hash) {
unsigned char *mac;
for (j = 0; j < num_recs; j++) {
thisrr = &rr[j];
if (thisrr->length < mac_size) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
return -1;
}
thisrr->length -= mac_size;
mac = thisrr->data + thisrr->length;
i = s->method->ssl3_enc->mac(s, thisrr, md, 0 /* not send */ );
if (i == 0 || CRYPTO_memcmp(md, mac, mac_size) != 0) {
SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
return -1;
}
}
/*
* We've handled the mac now - there is no MAC inside the encrypted
* record
*/
mac_size = 0;
}
if (mac_size > 0) {
macbufs = OPENSSL_zalloc(sizeof(*macbufs) * num_recs);
if (macbufs == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return -1;
}
}
+ ERR_set_mark();
enc_err = s->method->ssl3_enc->enc(s, rr, num_recs, 0, macbufs, mac_size);
/*-
* enc_err is:
* 0: if the record is publicly invalid, or an internal error, or AEAD
* decryption failed, or ETM decryption failed.
* 1: Success or MTE decryption failed (MAC will be randomised)
*/
if (enc_err == 0) {
if (ossl_statem_in_error(s)) {
/* SSLfatal() already got called */
+ ERR_clear_last_mark();
goto end;
}
if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
/*
* Valid early_data that we cannot decrypt will fail here. We treat
* it like an empty record.
*/
+ /*
+ * Remove any errors from the stack. Decryption failures are normal
+ * behaviour.
+ */
+ ERR_pop_to_mark();
+
thisrr = &rr[0];
if (!early_data_count_ok(s, thisrr->length,
EARLY_DATA_CIPHERTEXT_OVERHEAD, 0)) {
/* SSLfatal() already called */
goto end;
}
thisrr->length = 0;
thisrr->read = 1;
RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
RECORD_LAYER_reset_read_sequence(&s->rlayer);
ret = 1;
goto end;
}
+ ERR_clear_last_mark();
SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
goto end;
+ } else {
+ ERR_clear_last_mark();
}
OSSL_TRACE_BEGIN(TLS) {
BIO_printf(trc_out, "dec %lu\n", (unsigned long)rr[0].length);
BIO_dump_indent(trc_out, rr[0].data, rr[0].length, 4);
} OSSL_TRACE_END(TLS);
/* r->length is now the compressed data plus mac */
if ((sess != NULL)
&& (s->enc_read_ctx != NULL)
&& (!SSL_READ_ETM(s) && EVP_MD_CTX_get0_md(s->read_hash) != NULL)) {
/* s->read_hash != NULL => mac_size != -1 */
for (j = 0; j < num_recs; j++) {
SSL_MAC_BUF *thismb = &macbufs[j];
thisrr = &rr[j];
i = s->method->ssl3_enc->mac(s, thisrr, md, 0 /* not send */ );
if (i == 0 || thismb == NULL || thismb->mac == NULL
|| CRYPTO_memcmp(md, thismb->mac, (size_t)mac_size) != 0)
enc_err = 0;
if (thisrr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
enc_err = 0;
}
}
if (enc_err == 0) {
if (ossl_statem_in_error(s)) {
/* We already called SSLfatal() */
goto end;
}
/*
* A separate 'decryption_failed' alert was introduced with TLS 1.0,
* SSL 3.0 only has 'bad_record_mac'. But unless a decryption
* failure is directly visible from the ciphertext anyway, we should
* not reveal which kind of error occurred -- this might become
* visible to an attacker (e.g. via a logfile)
*/
SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
goto end;
}
skip_decryption:
for (j = 0; j < num_recs; j++) {
thisrr = &rr[j];
/* thisrr->length is now just compressed */
if (s->expand != NULL) {
if (thisrr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_COMPRESSED_LENGTH_TOO_LONG);
goto end;
}
if (!ssl3_do_uncompress(s, thisrr)) {
SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE,
SSL_R_BAD_DECOMPRESSION);
goto end;
}
}
if (SSL_IS_TLS13(s)
&& s->enc_read_ctx != NULL
&& thisrr->type != SSL3_RT_ALERT) {
size_t end;
if (thisrr->length == 0
|| thisrr->type != SSL3_RT_APPLICATION_DATA) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE);
goto end;
}
/* Strip trailing padding */
for (end = thisrr->length - 1; end > 0 && thisrr->data[end] == 0;
end--)
continue;
thisrr->length = end;
thisrr->type = thisrr->data[end];
if (thisrr->type != SSL3_RT_APPLICATION_DATA
&& thisrr->type != SSL3_RT_ALERT
&& thisrr->type != SSL3_RT_HANDSHAKE) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE);
goto end;
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_INNER_CONTENT_TYPE,
&thisrr->data[end], 1, s, s->msg_callback_arg);
}
/*
* TLSv1.3 alert and handshake records are required to be non-zero in
* length.
*/
if (SSL_IS_TLS13(s)
&& (thisrr->type == SSL3_RT_HANDSHAKE
|| thisrr->type == SSL3_RT_ALERT)
&& thisrr->length == 0) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_LENGTH);
goto end;
}
/*
* Usually thisrr->length is the length of a single record, but when
* KTLS handles the decryption, thisrr->length may be larger than
* SSL3_RT_MAX_PLAIN_LENGTH because the kernel may have coalesced
* multiple records.
* Therefore we have to rely on KTLS to check the plaintext length
* limit in the kernel.
*/
if (thisrr->length > SSL3_RT_MAX_PLAIN_LENGTH
&& (!BIO_get_ktls_recv(s->rbio) || is_ktls_left)) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
goto end;
}
/*
* Check if the received packet overflows the current
* Max Fragment Length setting.
* Note: USE_MAX_FRAGMENT_LENGTH_EXT and KTLS are mutually exclusive.
*/
if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
&& thisrr->length > GET_MAX_FRAGMENT_LENGTH(s->session)) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
goto end;
}
thisrr->off = 0;
/*-
* So at this point the following is true
* thisrr->type is the type of record
* thisrr->length == number of bytes in record
* thisrr->off == offset to first valid byte
* thisrr->data == where to take bytes from, increment after use :-).
*/
/* just read a 0 length packet */
if (thisrr->length == 0) {
RECORD_LAYER_inc_empty_record_count(&s->rlayer);
if (RECORD_LAYER_get_empty_record_count(&s->rlayer)
> MAX_EMPTY_RECORDS) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_RECORD_TOO_SMALL);
goto end;
}
} else {
RECORD_LAYER_reset_empty_record_count(&s->rlayer);
}
}
if (s->early_data_state == SSL_EARLY_DATA_READING) {
thisrr = &rr[0];
if (thisrr->type == SSL3_RT_APPLICATION_DATA
&& !early_data_count_ok(s, thisrr->length, 0, 0)) {
/* SSLfatal already called */
goto end;
}
}
RECORD_LAYER_set_numrpipes(&s->rlayer, num_recs);
ret = 1;
end:
if (macbufs != NULL) {
for (j = 0; j < num_recs; j++) {
if (macbufs[j].alloced)
OPENSSL_free(macbufs[j].mac);
}
OPENSSL_free(macbufs);
}
return ret;
}
int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr)
{
#ifndef OPENSSL_NO_COMP
int i;
if (rr->comp == NULL) {
rr->comp = (unsigned char *)
OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH);
}
if (rr->comp == NULL)
return 0;
i = COMP_expand_block(ssl->expand, rr->comp,
SSL3_RT_MAX_PLAIN_LENGTH, rr->data, (int)rr->length);
if (i < 0)
return 0;
else
rr->length = i;
rr->data = rr->comp;
#endif
return 1;
}
int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr)
{
#ifndef OPENSSL_NO_COMP
int i;
i = COMP_compress_block(ssl->compress, wr->data,
(int)(wr->length + SSL3_RT_MAX_COMPRESSED_OVERHEAD),
wr->input, (int)wr->length);
if (i < 0)
return 0;
else
wr->length = i;
wr->input = wr->data;
#endif
return 1;
}
/*-
* ssl3_enc encrypts/decrypts |n_recs| records in |inrecs|. Calls SSLfatal on
* internal error, but not otherwise. It is the responsibility of the caller to
* report a bad_record_mac
*
* Returns:
* 0: if the record is publicly invalid, or an internal error
* 1: Success or Mac-then-encrypt decryption failed (MAC will be randomised)
*/
int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int sending,
SSL_MAC_BUF *mac, size_t macsize)
{
SSL3_RECORD *rec;
EVP_CIPHER_CTX *ds;
size_t l, i;
size_t bs;
const EVP_CIPHER *enc;
rec = inrecs;
/*
* We shouldn't ever be called with more than one record in the SSLv3 case
*/
if (n_recs != 1)
return 0;
if (sending) {
ds = s->enc_write_ctx;
if (s->enc_write_ctx == NULL)
enc = NULL;
else
enc = EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx);
} else {
ds = s->enc_read_ctx;
if (s->enc_read_ctx == NULL)
enc = NULL;
else
enc = EVP_CIPHER_CTX_get0_cipher(s->enc_read_ctx);
}
if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
memmove(rec->data, rec->input, rec->length);
rec->input = rec->data;
} else {
int provided = (EVP_CIPHER_get0_provider(enc) != NULL);
l = rec->length;
bs = EVP_CIPHER_CTX_get_block_size(ds);
/* COMPRESS */
if ((bs != 1) && sending && !provided) {
/*
* We only do this for legacy ciphers. Provided ciphers add the
* padding on the provider side.
*/
i = bs - (l % bs);
/* we need to add 'i-1' padding bytes */
l += i;
/*
* the last of these zero bytes will be overwritten with the
* padding length.
*/
memset(&rec->input[rec->length], 0, i);
rec->length += i;
rec->input[l - 1] = (unsigned char)(i - 1);
}
if (!sending) {
if (l == 0 || l % bs != 0) {
/* Publicly invalid */
return 0;
}
/* otherwise, rec->length >= bs */
}
if (EVP_CIPHER_get0_provider(enc) != NULL) {
int outlen;
if (!EVP_CipherUpdate(ds, rec->data, &outlen, rec->input,
(unsigned int)l))
return 0;
rec->length = outlen;
if (!sending && mac != NULL) {
/* Now get a pointer to the MAC */
OSSL_PARAM params[2], *p = params;
/* Get the MAC */
mac->alloced = 0;
*p++ = OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_TLS_MAC,
(void **)&mac->mac,
macsize);
*p = OSSL_PARAM_construct_end();
if (!EVP_CIPHER_CTX_get_params(ds, params)) {
/* Shouldn't normally happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
} else {
if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1) {
/* Shouldn't happen */
SSLfatal(s, SSL_AD_BAD_RECORD_MAC, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!sending)
return ssl3_cbc_remove_padding_and_mac(&rec->length,
rec->orig_len,
rec->data,
(mac != NULL) ? &mac->mac : NULL,
(mac != NULL) ? &mac->alloced : NULL,
bs,
macsize,
s->ctx->libctx);
}
}
return 1;
}
#define MAX_PADDING 256
/*-
* tls1_enc encrypts/decrypts |n_recs| in |recs|. Calls SSLfatal on internal
* error, but not otherwise. It is the responsibility of the caller to report
* a bad_record_mac - if appropriate (DTLS just drops the record).
*
* Returns:
* 0: if the record is publicly invalid, or an internal error, or AEAD
* decryption failed, or Encrypt-then-mac decryption failed.
* 1: Success or Mac-then-encrypt decryption failed (MAC will be randomised)
*/
int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending,
SSL_MAC_BUF *macs, size_t macsize)
{
EVP_CIPHER_CTX *ds;
size_t reclen[SSL_MAX_PIPELINES];
unsigned char buf[SSL_MAX_PIPELINES][EVP_AEAD_TLS1_AAD_LEN];
+ unsigned char *data[SSL_MAX_PIPELINES];
int i, pad = 0, tmpr;
size_t bs, ctr, padnum, loop;
unsigned char padval;
const EVP_CIPHER *enc;
int tlstree_enc = sending ? (s->mac_flags & SSL_MAC_FLAG_WRITE_MAC_TLSTREE)
: (s->mac_flags & SSL_MAC_FLAG_READ_MAC_TLSTREE);
if (n_recs == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (sending) {
if (EVP_MD_CTX_get0_md(s->write_hash)) {
int n = EVP_MD_CTX_get_size(s->write_hash);
if (!ossl_assert(n >= 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
ds = s->enc_write_ctx;
if (s->enc_write_ctx == NULL)
enc = NULL;
else {
int ivlen;
enc = EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx);
/* For TLSv1.1 and later explicit IV */
if (SSL_USE_EXPLICIT_IV(s)
&& EVP_CIPHER_get_mode(enc) == EVP_CIPH_CBC_MODE)
ivlen = EVP_CIPHER_get_iv_length(enc);
else
ivlen = 0;
if (ivlen > 1) {
for (ctr = 0; ctr < n_recs; ctr++) {
if (recs[ctr].data != recs[ctr].input) {
/*
* we can't write into the input stream: Can this ever
* happen?? (steve)
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
} else if (RAND_bytes_ex(s->ctx->libctx, recs[ctr].input,
ivlen, 0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
}
}
} else {
if (EVP_MD_CTX_get0_md(s->read_hash)) {
int n = EVP_MD_CTX_get_size(s->read_hash);
if (!ossl_assert(n >= 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
ds = s->enc_read_ctx;
if (s->enc_read_ctx == NULL)
enc = NULL;
else
enc = EVP_CIPHER_CTX_get0_cipher(s->enc_read_ctx);
}
if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
for (ctr = 0; ctr < n_recs; ctr++) {
memmove(recs[ctr].data, recs[ctr].input, recs[ctr].length);
recs[ctr].input = recs[ctr].data;
}
} else {
int provided = (EVP_CIPHER_get0_provider(enc) != NULL);
bs = EVP_CIPHER_get_block_size(EVP_CIPHER_CTX_get0_cipher(ds));
if (n_recs > 1) {
if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ds))
& EVP_CIPH_FLAG_PIPELINE) == 0) {
/*
* We shouldn't have been called with pipeline data if the
* cipher doesn't support pipelining
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_PIPELINE_FAILURE);
return 0;
}
}
for (ctr = 0; ctr < n_recs; ctr++) {
reclen[ctr] = recs[ctr].length;
if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ds))
& EVP_CIPH_FLAG_AEAD_CIPHER) != 0) {
unsigned char *seq;
seq = sending ? RECORD_LAYER_get_write_sequence(&s->rlayer)
: RECORD_LAYER_get_read_sequence(&s->rlayer);
if (SSL_IS_DTLS(s)) {
/* DTLS does not support pipelining */
unsigned char dtlsseq[8], *p = dtlsseq;
s2n(sending ? DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer) :
DTLS_RECORD_LAYER_get_r_epoch(&s->rlayer), p);
memcpy(p, &seq[2], 6);
memcpy(buf[ctr], dtlsseq, 8);
} else {
memcpy(buf[ctr], seq, 8);
for (i = 7; i >= 0; i--) { /* increment */
++seq[i];
if (seq[i] != 0)
break;
}
}
buf[ctr][8] = recs[ctr].type;
buf[ctr][9] = (unsigned char)(s->version >> 8);
buf[ctr][10] = (unsigned char)(s->version);
buf[ctr][11] = (unsigned char)(recs[ctr].length >> 8);
buf[ctr][12] = (unsigned char)(recs[ctr].length & 0xff);
pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD,
EVP_AEAD_TLS1_AAD_LEN, buf[ctr]);
if (pad <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (sending) {
reclen[ctr] += pad;
recs[ctr].length += pad;
}
} else if ((bs != 1) && sending && !provided) {
/*
* We only do this for legacy ciphers. Provided ciphers add the
* padding on the provider side.
*/
padnum = bs - (reclen[ctr] % bs);
/* Add weird padding of up to 256 bytes */
if (padnum > MAX_PADDING) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
/* we need to add 'padnum' padding bytes of value padval */
padval = (unsigned char)(padnum - 1);
for (loop = reclen[ctr]; loop < reclen[ctr] + padnum; loop++)
recs[ctr].input[loop] = padval;
reclen[ctr] += padnum;
recs[ctr].length += padnum;
}
if (!sending) {
if (reclen[ctr] == 0 || reclen[ctr] % bs != 0) {
/* Publicly invalid */
return 0;
}
}
}
if (n_recs > 1) {
- unsigned char *data[SSL_MAX_PIPELINES];
-
/* Set the output buffers */
for (ctr = 0; ctr < n_recs; ctr++) {
data[ctr] = recs[ctr].data;
}
if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS,
(int)n_recs, data) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_PIPELINE_FAILURE);
return 0;
}
/* Set the input buffers */
for (ctr = 0; ctr < n_recs; ctr++) {
data[ctr] = recs[ctr].input;
}
if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_BUFS,
(int)n_recs, data) <= 0
|| EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_LENS,
(int)n_recs, reclen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_PIPELINE_FAILURE);
return 0;
}
}
if (!SSL_IS_DTLS(s) && tlstree_enc) {
unsigned char *seq;
int decrement_seq = 0;
/*
* When sending, seq is incremented after MAC calculation.
* So if we are in ETM mode, we use seq 'as is' in the ctrl-function.
* Otherwise we have to decrease it in the implementation
*/
if (sending && !SSL_WRITE_ETM(s))
decrement_seq = 1;
seq = sending ? RECORD_LAYER_get_write_sequence(&s->rlayer)
: RECORD_LAYER_get_read_sequence(&s->rlayer);
if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_TLSTREE, decrement_seq, seq) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
if (provided) {
int outlen;
/* Provided cipher - we do not support pipelining on this path */
if (n_recs > 1) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!EVP_CipherUpdate(ds, recs[0].data, &outlen, recs[0].input,
(unsigned int)reclen[0]))
return 0;
recs[0].length = outlen;
/*
* The length returned from EVP_CipherUpdate above is the actual
* payload length. We need to adjust the data/input ptr to skip over
* any explicit IV
*/
if (!sending) {
if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_GCM_MODE) {
recs[0].data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
recs[0].input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
} else if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_CCM_MODE) {
recs[0].data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
recs[0].input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
} else if (bs != 1 && SSL_USE_EXPLICIT_IV(s)) {
recs[0].data += bs;
recs[0].input += bs;
recs[0].orig_len -= bs;
}
/* Now get a pointer to the MAC (if applicable) */
if (macs != NULL) {
OSSL_PARAM params[2], *p = params;
/* Get the MAC */
macs[0].alloced = 0;
*p++ = OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_TLS_MAC,
(void **)&macs[0].mac,
macsize);
*p = OSSL_PARAM_construct_end();
if (!EVP_CIPHER_CTX_get_params(ds, params)) {
/* Shouldn't normally happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
}
} else {
/* Legacy cipher */
tmpr = EVP_Cipher(ds, recs[0].data, recs[0].input,
(unsigned int)reclen[0]);
if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ds))
& EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0
? (tmpr < 0)
: (tmpr == 0)) {
/* AEAD can fail to verify MAC */
return 0;
}
if (!sending) {
for (ctr = 0; ctr < n_recs; ctr++) {
/* Adjust the record to remove the explicit IV/MAC/Tag */
if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_GCM_MODE) {
recs[ctr].data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
recs[ctr].input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
recs[ctr].length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
} else if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_CCM_MODE) {
recs[ctr].data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
recs[ctr].input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
recs[ctr].length -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
} else if (bs != 1 && SSL_USE_EXPLICIT_IV(s)) {
if (recs[ctr].length < bs)
return 0;
recs[ctr].data += bs;
recs[ctr].input += bs;
recs[ctr].length -= bs;
recs[ctr].orig_len -= bs;
}
/*
* If using Mac-then-encrypt, then this will succeed but
* with a random MAC if padding is invalid
*/
if (!tls1_cbc_remove_padding_and_mac(&recs[ctr].length,
recs[ctr].orig_len,
recs[ctr].data,
(macs != NULL) ? &macs[ctr].mac : NULL,
(macs != NULL) ? &macs[ctr].alloced
: NULL,
bs,
pad ? (size_t)pad : macsize,
(EVP_CIPHER_get_flags(enc)
& EVP_CIPH_FLAG_AEAD_CIPHER) != 0,
s->ctx->libctx))
return 0;
}
}
}
}
return 1;
}
/*
* ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function
* which ssl3_cbc_digest_record supports.
*/
char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
{
switch (EVP_MD_CTX_get_type(ctx)) {
case NID_md5:
case NID_sha1:
case NID_sha224:
case NID_sha256:
case NID_sha384:
case NID_sha512:
return 1;
default:
return 0;
}
}
int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
{
unsigned char *mac_sec, *seq;
const EVP_MD_CTX *hash;
unsigned char *p, rec_char;
size_t md_size;
size_t npad;
int t;
if (sending) {
mac_sec = &(ssl->s3.write_mac_secret[0]);
seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
hash = ssl->write_hash;
} else {
mac_sec = &(ssl->s3.read_mac_secret[0]);
seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer);
hash = ssl->read_hash;
}
t = EVP_MD_CTX_get_size(hash);
if (t <= 0)
return 0;
md_size = t;
npad = (48 / md_size) * md_size;
if (!sending
&& EVP_CIPHER_CTX_get_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE
&& ssl3_cbc_record_digest_supported(hash)) {
#ifdef OPENSSL_NO_DEPRECATED_3_0
return 0;
#else
/*
* This is a CBC-encrypted record. We must avoid leaking any
* timing-side channel information about how many blocks of data we
* are hashing because that gives an attacker a timing-oracle.
*/
/*-
* npad is, at most, 48 bytes and that's with MD5:
* 16 + 48 + 8 (sequence bytes) + 1 + 2 = 75.
*
* With SHA-1 (the largest hash speced for SSLv3) the hash size
* goes up 4, but npad goes down by 8, resulting in a smaller
* total size.
*/
unsigned char header[75];
size_t j = 0;
memcpy(header + j, mac_sec, md_size);
j += md_size;
memcpy(header + j, ssl3_pad_1, npad);
j += npad;
memcpy(header + j, seq, 8);
j += 8;
header[j++] = rec->type;
header[j++] = (unsigned char)(rec->length >> 8);
header[j++] = (unsigned char)(rec->length & 0xff);
/* Final param == is SSLv3 */
if (ssl3_cbc_digest_record(EVP_MD_CTX_get0_md(hash),
md, &md_size,
header, rec->input,
rec->length, rec->orig_len,
mac_sec, md_size, 1) <= 0)
return 0;
#endif
} else {
unsigned int md_size_u;
/* Chop the digest off the end :-) */
EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
if (md_ctx == NULL)
return 0;
rec_char = rec->type;
p = md;
s2n(rec->length, p);
if (EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0
|| EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0
|| EVP_DigestUpdate(md_ctx, ssl3_pad_1, npad) <= 0
|| EVP_DigestUpdate(md_ctx, seq, 8) <= 0
|| EVP_DigestUpdate(md_ctx, &rec_char, 1) <= 0
|| EVP_DigestUpdate(md_ctx, md, 2) <= 0
|| EVP_DigestUpdate(md_ctx, rec->input, rec->length) <= 0
|| EVP_DigestFinal_ex(md_ctx, md, NULL) <= 0
|| EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0
|| EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0
|| EVP_DigestUpdate(md_ctx, ssl3_pad_2, npad) <= 0
|| EVP_DigestUpdate(md_ctx, md, md_size) <= 0
|| EVP_DigestFinal_ex(md_ctx, md, &md_size_u) <= 0) {
EVP_MD_CTX_free(md_ctx);
return 0;
}
EVP_MD_CTX_free(md_ctx);
}
ssl3_record_sequence_update(seq);
return 1;
}
int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
{
unsigned char *seq;
EVP_MD_CTX *hash;
size_t md_size;
int i;
EVP_MD_CTX *hmac = NULL, *mac_ctx;
unsigned char header[13];
int stream_mac = sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
: (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM);
int tlstree_mac = sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_TLSTREE)
: (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_TLSTREE);
int t;
int ret = 0;
if (sending) {
seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
hash = ssl->write_hash;
} else {
seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer);
hash = ssl->read_hash;
}
t = EVP_MD_CTX_get_size(hash);
if (!ossl_assert(t >= 0))
return 0;
md_size = t;
/* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
if (stream_mac) {
mac_ctx = hash;
} else {
hmac = EVP_MD_CTX_new();
if (hmac == NULL || !EVP_MD_CTX_copy(hmac, hash)) {
goto end;
}
mac_ctx = hmac;
}
if (!SSL_IS_DTLS(ssl) && tlstree_mac && EVP_MD_CTX_ctrl(mac_ctx, EVP_MD_CTRL_TLSTREE, 0, seq) <= 0) {
goto end;
}
if (SSL_IS_DTLS(ssl)) {
unsigned char dtlsseq[8], *p = dtlsseq;
s2n(sending ? DTLS_RECORD_LAYER_get_w_epoch(&ssl->rlayer) :
DTLS_RECORD_LAYER_get_r_epoch(&ssl->rlayer), p);
memcpy(p, &seq[2], 6);
memcpy(header, dtlsseq, 8);
} else
memcpy(header, seq, 8);
header[8] = rec->type;
header[9] = (unsigned char)(ssl->version >> 8);
header[10] = (unsigned char)(ssl->version);
header[11] = (unsigned char)(rec->length >> 8);
header[12] = (unsigned char)(rec->length & 0xff);
if (!sending && !SSL_READ_ETM(ssl)
&& EVP_CIPHER_CTX_get_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE
&& ssl3_cbc_record_digest_supported(mac_ctx)) {
OSSL_PARAM tls_hmac_params[2], *p = tls_hmac_params;
*p++ = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_TLS_DATA_SIZE,
&rec->orig_len);
*p++ = OSSL_PARAM_construct_end();
if (!EVP_PKEY_CTX_set_params(EVP_MD_CTX_get_pkey_ctx(mac_ctx),
tls_hmac_params)) {
goto end;
}
}
if (EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)) <= 0
|| EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length) <= 0
|| EVP_DigestSignFinal(mac_ctx, md, &md_size) <= 0) {
goto end;
}
OSSL_TRACE_BEGIN(TLS) {
BIO_printf(trc_out, "seq:\n");
BIO_dump_indent(trc_out, seq, 8, 4);
BIO_printf(trc_out, "rec:\n");
BIO_dump_indent(trc_out, rec->data, rec->length, 4);
} OSSL_TRACE_END(TLS);
if (!SSL_IS_DTLS(ssl)) {
for (i = 7; i >= 0; i--) {
++seq[i];
if (seq[i] != 0)
break;
}
}
OSSL_TRACE_BEGIN(TLS) {
BIO_printf(trc_out, "md:\n");
BIO_dump_indent(trc_out, md, md_size, 4);
} OSSL_TRACE_END(TLS);
ret = 1;
end:
EVP_MD_CTX_free(hmac);
return ret;
}
int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
{
int i;
int enc_err;
SSL_SESSION *sess;
SSL3_RECORD *rr;
int imac_size;
size_t mac_size = 0;
unsigned char md[EVP_MAX_MD_SIZE];
size_t max_plain_length = SSL3_RT_MAX_PLAIN_LENGTH;
SSL_MAC_BUF macbuf = { NULL, 0 };
int ret = 0;
rr = RECORD_LAYER_get_rrec(&s->rlayer);
sess = s->session;
/*
* At this point, s->rlayer.packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
* and we have that many bytes in s->rlayer.packet
*/
rr->input = &(RECORD_LAYER_get_packet(&s->rlayer)[DTLS1_RT_HEADER_LENGTH]);
/*
* ok, we can now read from 's->rlayer.packet' data into 'rr'. rr->input
* points at rr->length bytes, which need to be copied into rr->data by
* either the decryption or by the decompression. When the data is 'copied'
* into the rr->data buffer, rr->input will be pointed at the new buffer
*/
/*
* We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length
* bytes of encrypted compressed stuff.
*/
/* check is not needed I believe */
if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
return 0;
}
/* decrypt in place in 'rr->input' */
rr->data = rr->input;
rr->orig_len = rr->length;
if (s->read_hash != NULL) {
const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(s->read_hash);
if (tmpmd != NULL) {
imac_size = EVP_MD_get_size(tmpmd);
if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
return 0;
}
mac_size = (size_t)imac_size;
}
}
if (SSL_READ_ETM(s) && s->read_hash) {
unsigned char *mac;
if (rr->orig_len < mac_size) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
return 0;
}
rr->length -= mac_size;
mac = rr->data + rr->length;
i = s->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
if (i == 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) {
SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
return 0;
}
/*
* We've handled the mac now - there is no MAC inside the encrypted
* record
*/
mac_size = 0;
}
/*
* Set a mark around the packet decryption attempt. This is DTLS, so
* bad packets are just ignored, and we don't want to leave stray
* errors in the queue from processing bogus junk that we ignored.
*/
ERR_set_mark();
enc_err = s->method->ssl3_enc->enc(s, rr, 1, 0, &macbuf, mac_size);
/*-
* enc_err is:
* 0: if the record is publicly invalid, or an internal error, or AEAD
* decryption failed, or ETM decryption failed.
* 1: Success or MTE decryption failed (MAC will be randomised)
*/
if (enc_err == 0) {
ERR_pop_to_mark();
if (ossl_statem_in_error(s)) {
/* SSLfatal() got called */
goto end;
}
/* For DTLS we simply ignore bad packets. */
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto end;
}
ERR_clear_last_mark();
OSSL_TRACE_BEGIN(TLS) {
BIO_printf(trc_out, "dec %zd\n", rr->length);
BIO_dump_indent(trc_out, rr->data, rr->length, 4);
} OSSL_TRACE_END(TLS);
/* r->length is now the compressed data plus mac */
if ((sess != NULL)
&& !SSL_READ_ETM(s)
&& (s->enc_read_ctx != NULL)
&& (EVP_MD_CTX_get0_md(s->read_hash) != NULL)) {
/* s->read_hash != NULL => mac_size != -1 */
i = s->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
if (i == 0 || macbuf.mac == NULL
|| CRYPTO_memcmp(md, macbuf.mac, mac_size) != 0)
enc_err = 0;
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
enc_err = 0;
}
if (enc_err == 0) {
/* decryption failed, silently discard message */
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto end;
}
/* r->length is now just compressed */
if (s->expand != NULL) {
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_COMPRESSED_LENGTH_TOO_LONG);
goto end;
}
if (!ssl3_do_uncompress(s, rr)) {
SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE, SSL_R_BAD_DECOMPRESSION);
goto end;
}
}
/* use current Max Fragment Length setting if applicable */
if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
max_plain_length = GET_MAX_FRAGMENT_LENGTH(s->session);
/* send overflow if the plaintext is too long now it has passed MAC */
if (rr->length > max_plain_length) {
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
goto end;
}
rr->off = 0;
/*-
* So at this point the following is true
* ssl->s3.rrec.type is the type of record
* ssl->s3.rrec.length == number of bytes in record
* ssl->s3.rrec.off == offset to first valid byte
* ssl->s3.rrec.data == where to take bytes from, increment
* after use :-).
*/
/* we have pulled in a full packet so zero things */
RECORD_LAYER_reset_packet_length(&s->rlayer);
/* Mark receipt of record. */
dtls1_record_bitmap_update(s, bitmap);
ret = 1;
end:
if (macbuf.alloced)
OPENSSL_free(macbuf.mac);
return ret;
}
/*
* Retrieve a buffered record that belongs to the current epoch, i.e. processed
*/
#define dtls1_get_processed_record(s) \
dtls1_retrieve_buffered_record((s), \
&(DTLS_RECORD_LAYER_get_processed_rcds(&s->rlayer)))
/*-
* Call this to get a new input record.
* It will return <= 0 if more data is needed, normally due to an error
* or non-blocking IO.
* When it finishes, one packet has been decoded and can be found in
* ssl->s3.rrec.type - is the type of record
* ssl->s3.rrec.data - data
* ssl->s3.rrec.length - number of bytes
*/
/* used only by dtls1_read_bytes */
int dtls1_get_record(SSL *s)
{
int ssl_major, ssl_minor;
int rret;
size_t more, n;
SSL3_RECORD *rr;
unsigned char *p = NULL;
unsigned short version;
DTLS1_BITMAP *bitmap;
unsigned int is_next_epoch;
rr = RECORD_LAYER_get_rrec(&s->rlayer);
again:
/*
* The epoch may have changed. If so, process all the pending records.
* This is a non-blocking operation.
*/
if (!dtls1_process_buffered_records(s)) {
/* SSLfatal() already called */
return -1;
}
/* if we're renegotiating, then there may be buffered records */
if (dtls1_get_processed_record(s))
return 1;
/* get something from the wire */
/* check if we have the header */
if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
(RECORD_LAYER_get_packet_length(&s->rlayer) < DTLS1_RT_HEADER_LENGTH)) {
rret = ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH,
SSL3_BUFFER_get_len(&s->rlayer.rbuf), 0, 1, &n);
/* read timeout is handled by dtls1_read_bytes */
if (rret <= 0) {
/* SSLfatal() already called if appropriate */
return rret; /* error or non-blocking */
}
/* this packet contained a partial record, dump it */
if (RECORD_LAYER_get_packet_length(&s->rlayer) !=
DTLS1_RT_HEADER_LENGTH) {
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
p = RECORD_LAYER_get_packet(&s->rlayer);
if (s->msg_callback)
s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH,
s, s->msg_callback_arg);
/* Pull apart the header into the DTLS1_RECORD */
rr->type = *(p++);
ssl_major = *(p++);
ssl_minor = *(p++);
version = (ssl_major << 8) | ssl_minor;
/* sequence number is 64 bits, with top 2 bytes = epoch */
n2s(p, rr->epoch);
memcpy(&(RECORD_LAYER_get_read_sequence(&s->rlayer)[2]), p, 6);
p += 6;
n2s(p, rr->length);
rr->read = 0;
/*
* Lets check the version. We tolerate alerts that don't have the exact
* version number (e.g. because of protocol version errors)
*/
if (!s->first_packet && rr->type != SSL3_RT_ALERT) {
if (version != s->version) {
/* unexpected version, silently discard */
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
}
if ((version & 0xff00) != (s->version & 0xff00)) {
/* wrong version, silently discard record */
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
/* record too long, silently discard it */
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
/* If received packet overflows own-client Max Fragment Length setting */
if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
&& rr->length > GET_MAX_FRAGMENT_LENGTH(s->session) + SSL3_RT_MAX_ENCRYPTED_OVERHEAD) {
/* record too long, silently discard it */
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
/* now s->rlayer.rstate == SSL_ST_READ_BODY */
}
/* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data */
if (rr->length >
RECORD_LAYER_get_packet_length(&s->rlayer) - DTLS1_RT_HEADER_LENGTH) {
/* now s->rlayer.packet_length == DTLS1_RT_HEADER_LENGTH */
more = rr->length;
rret = ssl3_read_n(s, more, more, 1, 1, &n);
/* this packet contained a partial record, dump it */
if (rret <= 0 || n != more) {
if (ossl_statem_in_error(s)) {
/* ssl3_read_n() called SSLfatal() */
return -1;
}
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
/*
* now n == rr->length, and s->rlayer.packet_length ==
* DTLS1_RT_HEADER_LENGTH + rr->length
*/
}
/* set state for later operations */
RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER);
/* match epochs. NULL means the packet is dropped on the floor */
bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
if (bitmap == NULL) {
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
goto again; /* get another record */
}
#ifndef OPENSSL_NO_SCTP
/* Only do replay check if no SCTP bio */
if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) {
#endif
/* Check whether this is a repeat, or aged record. */
if (!dtls1_record_replay_check(s, bitmap)) {
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
goto again; /* get another record */
}
#ifndef OPENSSL_NO_SCTP
}
#endif
/* just read a 0 length packet */
if (rr->length == 0) {
rr->read = 1;
goto again;
}
/*
* If this record is from the next epoch (either HM or ALERT), and a
* handshake is currently in progress, buffer it since it cannot be
* processed at this time.
*/
if (is_next_epoch) {
if ((SSL_in_init(s) || ossl_statem_get_in_handshake(s))) {
if (dtls1_buffer_record (s,
&(DTLS_RECORD_LAYER_get_unprocessed_rcds(&s->rlayer)),
rr->seq_num) < 0) {
/* SSLfatal() already called */
return -1;
}
}
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
if (!dtls1_process_record(s, bitmap)) {
if (ossl_statem_in_error(s)) {
/* dtls1_process_record() called SSLfatal */
return -1;
}
rr->length = 0;
rr->read = 1;
RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
goto again; /* get another record */
}
return 1;
}
int dtls_buffer_listen_record(SSL *s, size_t len, unsigned char *seq, size_t off)
{
SSL3_RECORD *rr;
rr = RECORD_LAYER_get_rrec(&s->rlayer);
memset(rr, 0, sizeof(SSL3_RECORD));
rr->length = len;
rr->type = SSL3_RT_HANDSHAKE;
memcpy(rr->seq_num, seq, sizeof(rr->seq_num));
rr->off = off;
s->rlayer.packet = RECORD_LAYER_get_rbuf(&s->rlayer)->buf;
s->rlayer.packet_length = DTLS1_RT_HEADER_LENGTH + len;
rr->data = s->rlayer.packet + DTLS1_RT_HEADER_LENGTH;
if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds),
SSL3_RECORD_get_seq_num(s->rlayer.rrec)) <= 0) {
/* SSLfatal() already called */
return 0;
}
return 1;
}
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index e4168e74c276..2e2d09a32ee4 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -1,1132 +1,1154 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 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 <stdio.h>
#include <sys/types.h>
#include "internal/nelem.h"
#include "internal/o_dir.h"
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/store.h>
#include <openssl/x509v3.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include "internal/refcount.h"
#include "ssl_local.h"
#include "ssl_cert_table.h"
#include "internal/thread_once.h"
+#ifndef OPENSSL_NO_POSIX_IO
+# include <sys/stat.h>
+# ifdef _WIN32
+# define stat _stat
+# endif
+# ifndef S_ISDIR
+# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
+# endif
+#endif
+
static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx,
int op, int bits, int nid, void *other,
void *ex);
static CRYPTO_ONCE ssl_x509_store_ctx_once = CRYPTO_ONCE_STATIC_INIT;
static volatile int ssl_x509_store_ctx_idx = -1;
DEFINE_RUN_ONCE_STATIC(ssl_x509_store_ctx_init)
{
ssl_x509_store_ctx_idx = X509_STORE_CTX_get_ex_new_index(0,
"SSL for verify callback",
NULL, NULL, NULL);
return ssl_x509_store_ctx_idx >= 0;
}
int SSL_get_ex_data_X509_STORE_CTX_idx(void)
{
if (!RUN_ONCE(&ssl_x509_store_ctx_once, ssl_x509_store_ctx_init))
return -1;
return ssl_x509_store_ctx_idx;
}
CERT *ssl_cert_new(void)
{
CERT *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->key = &(ret->pkeys[SSL_PKEY_RSA]);
ret->references = 1;
ret->sec_cb = ssl_security_default_callback;
ret->sec_level = OPENSSL_TLS_SECURITY_LEVEL;
ret->sec_ex = NULL;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
return ret;
}
CERT *ssl_cert_dup(CERT *cert)
{
CERT *ret = OPENSSL_zalloc(sizeof(*ret));
int i;
if (ret == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->references = 1;
ret->key = &ret->pkeys[cert->key - cert->pkeys];
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
if (cert->dh_tmp != NULL) {
ret->dh_tmp = cert->dh_tmp;
EVP_PKEY_up_ref(ret->dh_tmp);
}
ret->dh_tmp_cb = cert->dh_tmp_cb;
ret->dh_tmp_auto = cert->dh_tmp_auto;
for (i = 0; i < SSL_PKEY_NUM; i++) {
CERT_PKEY *cpk = cert->pkeys + i;
CERT_PKEY *rpk = ret->pkeys + i;
if (cpk->x509 != NULL) {
rpk->x509 = cpk->x509;
X509_up_ref(rpk->x509);
}
if (cpk->privatekey != NULL) {
rpk->privatekey = cpk->privatekey;
EVP_PKEY_up_ref(cpk->privatekey);
}
if (cpk->chain) {
rpk->chain = X509_chain_up_ref(cpk->chain);
if (!rpk->chain) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if (cert->pkeys[i].serverinfo != NULL) {
/* Just copy everything. */
ret->pkeys[i].serverinfo =
OPENSSL_malloc(cert->pkeys[i].serverinfo_length);
if (ret->pkeys[i].serverinfo == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->pkeys[i].serverinfo_length = cert->pkeys[i].serverinfo_length;
memcpy(ret->pkeys[i].serverinfo,
cert->pkeys[i].serverinfo, cert->pkeys[i].serverinfo_length);
}
}
/* Configured sigalgs copied across */
if (cert->conf_sigalgs) {
ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen
* sizeof(*cert->conf_sigalgs));
if (ret->conf_sigalgs == NULL)
goto err;
memcpy(ret->conf_sigalgs, cert->conf_sigalgs,
cert->conf_sigalgslen * sizeof(*cert->conf_sigalgs));
ret->conf_sigalgslen = cert->conf_sigalgslen;
} else
ret->conf_sigalgs = NULL;
if (cert->client_sigalgs) {
ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen
* sizeof(*cert->client_sigalgs));
if (ret->client_sigalgs == NULL)
goto err;
memcpy(ret->client_sigalgs, cert->client_sigalgs,
cert->client_sigalgslen * sizeof(*cert->client_sigalgs));
ret->client_sigalgslen = cert->client_sigalgslen;
} else
ret->client_sigalgs = NULL;
/* Copy any custom client certificate types */
if (cert->ctype) {
ret->ctype = OPENSSL_memdup(cert->ctype, cert->ctype_len);
if (ret->ctype == NULL)
goto err;
ret->ctype_len = cert->ctype_len;
}
ret->cert_flags = cert->cert_flags;
ret->cert_cb = cert->cert_cb;
ret->cert_cb_arg = cert->cert_cb_arg;
if (cert->verify_store) {
X509_STORE_up_ref(cert->verify_store);
ret->verify_store = cert->verify_store;
}
if (cert->chain_store) {
X509_STORE_up_ref(cert->chain_store);
ret->chain_store = cert->chain_store;
}
ret->sec_cb = cert->sec_cb;
ret->sec_level = cert->sec_level;
ret->sec_ex = cert->sec_ex;
if (!custom_exts_copy(&ret->custext, &cert->custext))
goto err;
#ifndef OPENSSL_NO_PSK
if (cert->psk_identity_hint) {
ret->psk_identity_hint = OPENSSL_strdup(cert->psk_identity_hint);
if (ret->psk_identity_hint == NULL)
goto err;
}
#endif
return ret;
err:
ssl_cert_free(ret);
return NULL;
}
/* Free up and clear all certificates and chains */
void ssl_cert_clear_certs(CERT *c)
{
int i;
if (c == NULL)
return;
for (i = 0; i < SSL_PKEY_NUM; i++) {
CERT_PKEY *cpk = c->pkeys + i;
X509_free(cpk->x509);
cpk->x509 = NULL;
EVP_PKEY_free(cpk->privatekey);
cpk->privatekey = NULL;
sk_X509_pop_free(cpk->chain, X509_free);
cpk->chain = NULL;
OPENSSL_free(cpk->serverinfo);
cpk->serverinfo = NULL;
cpk->serverinfo_length = 0;
}
}
void ssl_cert_free(CERT *c)
{
int i;
if (c == NULL)
return;
CRYPTO_DOWN_REF(&c->references, &i, c->lock);
REF_PRINT_COUNT("CERT", c);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
EVP_PKEY_free(c->dh_tmp);
ssl_cert_clear_certs(c);
OPENSSL_free(c->conf_sigalgs);
OPENSSL_free(c->client_sigalgs);
OPENSSL_free(c->ctype);
X509_STORE_free(c->verify_store);
X509_STORE_free(c->chain_store);
custom_exts_free(&c->custext);
#ifndef OPENSSL_NO_PSK
OPENSSL_free(c->psk_identity_hint);
#endif
CRYPTO_THREAD_lock_free(c->lock);
OPENSSL_free(c);
}
int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
{
int i, r;
CERT_PKEY *cpk = s != NULL ? s->cert->key : ctx->cert->key;
if (!cpk)
return 0;
for (i = 0; i < sk_X509_num(chain); i++) {
X509 *x = sk_X509_value(chain, i);
r = ssl_security_cert(s, ctx, x, 0, 0);
if (r != 1) {
ERR_raise(ERR_LIB_SSL, r);
return 0;
}
}
sk_X509_pop_free(cpk->chain, X509_free);
cpk->chain = chain;
return 1;
}
int ssl_cert_set1_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
{
STACK_OF(X509) *dchain;
if (!chain)
return ssl_cert_set0_chain(s, ctx, NULL);
dchain = X509_chain_up_ref(chain);
if (!dchain)
return 0;
if (!ssl_cert_set0_chain(s, ctx, dchain)) {
sk_X509_pop_free(dchain, X509_free);
return 0;
}
return 1;
}
int ssl_cert_add0_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x)
{
int r;
CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key;
if (!cpk)
return 0;
r = ssl_security_cert(s, ctx, x, 0, 0);
if (r != 1) {
ERR_raise(ERR_LIB_SSL, r);
return 0;
}
if (!cpk->chain)
cpk->chain = sk_X509_new_null();
if (!cpk->chain || !sk_X509_push(cpk->chain, x))
return 0;
return 1;
}
int ssl_cert_add1_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x)
{
if (!ssl_cert_add0_chain_cert(s, ctx, x))
return 0;
X509_up_ref(x);
return 1;
}
int ssl_cert_select_current(CERT *c, X509 *x)
{
int i;
if (x == NULL)
return 0;
for (i = 0; i < SSL_PKEY_NUM; i++) {
CERT_PKEY *cpk = c->pkeys + i;
if (cpk->x509 == x && cpk->privatekey) {
c->key = cpk;
return 1;
}
}
for (i = 0; i < SSL_PKEY_NUM; i++) {
CERT_PKEY *cpk = c->pkeys + i;
if (cpk->privatekey && cpk->x509 && !X509_cmp(cpk->x509, x)) {
c->key = cpk;
return 1;
}
}
return 0;
}
int ssl_cert_set_current(CERT *c, long op)
{
int i, idx;
if (!c)
return 0;
if (op == SSL_CERT_SET_FIRST)
idx = 0;
else if (op == SSL_CERT_SET_NEXT) {
idx = (int)(c->key - c->pkeys + 1);
if (idx >= SSL_PKEY_NUM)
return 0;
} else
return 0;
for (i = idx; i < SSL_PKEY_NUM; i++) {
CERT_PKEY *cpk = c->pkeys + i;
if (cpk->x509 && cpk->privatekey) {
c->key = cpk;
return 1;
}
}
return 0;
}
void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg)
{
c->cert_cb = cb;
c->cert_cb_arg = arg;
}
/*
* Verify a certificate chain
* Return codes:
* 1: Verify success
* 0: Verify failure or error
* -1: Retry required
*/
int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
{
X509 *x;
int i = 0;
X509_STORE *verify_store;
X509_STORE_CTX *ctx = NULL;
X509_VERIFY_PARAM *param;
if ((sk == NULL) || (sk_X509_num(sk) == 0))
return 0;
if (s->cert->verify_store)
verify_store = s->cert->verify_store;
else
verify_store = s->ctx->cert_store;
ctx = X509_STORE_CTX_new_ex(s->ctx->libctx, s->ctx->propq);
if (ctx == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
x = sk_X509_value(sk, 0);
if (!X509_STORE_CTX_init(ctx, verify_store, x, sk)) {
ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB);
goto end;
}
param = X509_STORE_CTX_get0_param(ctx);
/*
* XXX: Separate @AUTHSECLEVEL and @TLSSECLEVEL would be useful at some
* point, for now a single @SECLEVEL sets the same policy for TLS crypto
* and PKI authentication.
*/
X509_VERIFY_PARAM_set_auth_level(param, SSL_get_security_level(s));
/* Set suite B flags if needed */
X509_STORE_CTX_set_flags(ctx, tls1_suiteb(s));
if (!X509_STORE_CTX_set_ex_data
(ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s)) {
goto end;
}
/* Verify via DANE if enabled */
if (DANETLS_ENABLED(&s->dane))
X509_STORE_CTX_set0_dane(ctx, &s->dane);
/*
* We need to inherit the verify parameters. These can be determined by
* the context: if its a server it will verify SSL client certificates or
* vice versa.
*/
X509_STORE_CTX_set_default(ctx, s->server ? "ssl_client" : "ssl_server");
/*
* Anything non-default in "s->param" should overwrite anything in the ctx.
*/
X509_VERIFY_PARAM_set1(param, s->param);
if (s->verify_callback)
X509_STORE_CTX_set_verify_cb(ctx, s->verify_callback);
if (s->ctx->app_verify_callback != NULL) {
i = s->ctx->app_verify_callback(ctx, s->ctx->app_verify_arg);
} else {
i = X509_verify_cert(ctx);
/* We treat an error in the same way as a failure to verify */
if (i < 0)
i = 0;
}
s->verify_result = X509_STORE_CTX_get_error(ctx);
sk_X509_pop_free(s->verified_chain, X509_free);
s->verified_chain = NULL;
if (X509_STORE_CTX_get0_chain(ctx) != NULL) {
s->verified_chain = X509_STORE_CTX_get1_chain(ctx);
if (s->verified_chain == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
i = 0;
}
}
/* Move peername from the store context params to the SSL handle's */
X509_VERIFY_PARAM_move_peername(s->param, param);
end:
X509_STORE_CTX_free(ctx);
return i;
}
static void set0_CA_list(STACK_OF(X509_NAME) **ca_list,
STACK_OF(X509_NAME) *name_list)
{
sk_X509_NAME_pop_free(*ca_list, X509_NAME_free);
*ca_list = name_list;
}
STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk)
{
int i;
const int num = sk_X509_NAME_num(sk);
STACK_OF(X509_NAME) *ret;
X509_NAME *name;
ret = sk_X509_NAME_new_reserve(NULL, num);
if (ret == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (i = 0; i < num; i++) {
name = X509_NAME_dup(sk_X509_NAME_value(sk, i));
if (name == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
sk_X509_NAME_pop_free(ret, X509_NAME_free);
return NULL;
}
sk_X509_NAME_push(ret, name); /* Cannot fail after reserve call */
}
return ret;
}
void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
{
set0_CA_list(&s->ca_names, name_list);
}
void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list)
{
set0_CA_list(&ctx->ca_names, name_list);
}
const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx)
{
return ctx->ca_names;
}
const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s)
{
return s->ca_names != NULL ? s->ca_names : s->ctx->ca_names;
}
void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list)
{
set0_CA_list(&ctx->client_ca_names, name_list);
}
STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx)
{
return ctx->client_ca_names;
}
void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
{
set0_CA_list(&s->client_ca_names, name_list);
}
const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s)
{
return s->s3.tmp.peer_ca_names;
}
STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s)
{
if (!s->server)
return s->s3.tmp.peer_ca_names;
return s->client_ca_names != NULL ? s->client_ca_names
: s->ctx->client_ca_names;
}
static int add_ca_name(STACK_OF(X509_NAME) **sk, const X509 *x)
{
X509_NAME *name;
if (x == NULL)
return 0;
if (*sk == NULL && ((*sk = sk_X509_NAME_new_null()) == NULL))
return 0;
if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL)
return 0;
if (!sk_X509_NAME_push(*sk, name)) {
X509_NAME_free(name);
return 0;
}
return 1;
}
int SSL_add1_to_CA_list(SSL *ssl, const X509 *x)
{
return add_ca_name(&ssl->ca_names, x);
}
int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x)
{
return add_ca_name(&ctx->ca_names, x);
}
/*
* The following two are older names are to be replaced with
* SSL(_CTX)_add1_to_CA_list
*/
int SSL_add_client_CA(SSL *ssl, X509 *x)
{
return add_ca_name(&ssl->client_ca_names, x);
}
int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)
{
return add_ca_name(&ctx->client_ca_names, x);
}
static int xname_cmp(const X509_NAME *a, const X509_NAME *b)
{
unsigned char *abuf = NULL, *bbuf = NULL;
int alen, blen, ret;
/* X509_NAME_cmp() itself casts away constness in this way, so
* assume it's safe:
*/
alen = i2d_X509_NAME((X509_NAME *)a, &abuf);
blen = i2d_X509_NAME((X509_NAME *)b, &bbuf);
if (alen < 0 || blen < 0)
ret = -2;
else if (alen != blen)
ret = alen - blen;
else /* alen == blen */
ret = memcmp(abuf, bbuf, alen);
OPENSSL_free(abuf);
OPENSSL_free(bbuf);
return ret;
}
static int xname_sk_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
{
return xname_cmp(*a, *b);
}
static unsigned long xname_hash(const X509_NAME *a)
{
/* This returns 0 also if SHA1 is not available */
return X509_NAME_hash_ex((X509_NAME *)a, NULL, NULL, NULL);
}
STACK_OF(X509_NAME) *SSL_load_client_CA_file_ex(const char *file,
OSSL_LIB_CTX *libctx,
const char *propq)
{
BIO *in = BIO_new(BIO_s_file());
X509 *x = NULL;
X509_NAME *xn = NULL;
STACK_OF(X509_NAME) *ret = NULL;
LHASH_OF(X509_NAME) *name_hash = lh_X509_NAME_new(xname_hash, xname_cmp);
OSSL_LIB_CTX *prev_libctx = NULL;
if ((name_hash == NULL) || (in == NULL)) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
x = X509_new_ex(libctx, propq);
if (x == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
if (BIO_read_filename(in, file) <= 0)
goto err;
/* Internally lh_X509_NAME_retrieve() needs the libctx to retrieve SHA1 */
prev_libctx = OSSL_LIB_CTX_set0_default(libctx);
for (;;) {
if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
break;
if (ret == NULL) {
ret = sk_X509_NAME_new_null();
if (ret == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if ((xn = X509_get_subject_name(x)) == NULL)
goto err;
/* check for duplicates */
xn = X509_NAME_dup(xn);
if (xn == NULL)
goto err;
if (lh_X509_NAME_retrieve(name_hash, xn) != NULL) {
/* Duplicate. */
X509_NAME_free(xn);
xn = NULL;
} else {
lh_X509_NAME_insert(name_hash, xn);
if (!sk_X509_NAME_push(ret, xn))
goto err;
}
}
goto done;
err:
X509_NAME_free(xn);
sk_X509_NAME_pop_free(ret, X509_NAME_free);
ret = NULL;
done:
/* restore the old libctx */
OSSL_LIB_CTX_set0_default(prev_libctx);
BIO_free(in);
X509_free(x);
lh_X509_NAME_free(name_hash);
if (ret != NULL)
ERR_clear_error();
return ret;
}
STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
{
return SSL_load_client_CA_file_ex(file, NULL, NULL);
}
int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
const char *file)
{
BIO *in;
X509 *x = NULL;
X509_NAME *xn = NULL;
int ret = 1;
int (*oldcmp) (const X509_NAME *const *a, const X509_NAME *const *b);
oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_sk_cmp);
in = BIO_new(BIO_s_file());
if (in == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
if (BIO_read_filename(in, file) <= 0)
goto err;
for (;;) {
if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
break;
if ((xn = X509_get_subject_name(x)) == NULL)
goto err;
xn = X509_NAME_dup(xn);
if (xn == NULL)
goto err;
if (sk_X509_NAME_find(stack, xn) >= 0) {
/* Duplicate. */
X509_NAME_free(xn);
} else if (!sk_X509_NAME_push(stack, xn)) {
X509_NAME_free(xn);
goto err;
}
}
ERR_clear_error();
goto done;
err:
ret = 0;
done:
BIO_free(in);
X509_free(x);
(void)sk_X509_NAME_set_cmp_func(stack, oldcmp);
return ret;
}
int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
const char *dir)
{
OPENSSL_DIR_CTX *d = NULL;
const char *filename;
int ret = 0;
/* Note that a side effect is that the CAs will be sorted by name */
while ((filename = OPENSSL_DIR_read(&d, dir))) {
char buf[1024];
int r;
+#ifndef OPENSSL_NO_POSIX_IO
+ struct stat st;
+#else
+ /* Cannot use stat so just skip current and parent directories */
+ if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
+ continue;
+#endif
if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) {
ERR_raise(ERR_LIB_SSL, SSL_R_PATH_TOO_LONG);
goto err;
}
#ifdef OPENSSL_SYS_VMS
r = BIO_snprintf(buf, sizeof(buf), "%s%s", dir, filename);
#else
r = BIO_snprintf(buf, sizeof(buf), "%s/%s", dir, filename);
+#endif
+#ifndef OPENSSL_NO_POSIX_IO
+ /* Skip subdirectories */
+ if (!stat(buf, &st) && S_ISDIR(st.st_mode))
+ continue;
#endif
if (r <= 0 || r >= (int)sizeof(buf))
goto err;
if (!SSL_add_file_cert_subjects_to_stack(stack, buf))
goto err;
}
if (errno) {
ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
"calling OPENSSL_dir_read(%s)", dir);
ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB);
goto err;
}
ret = 1;
err:
if (d)
OPENSSL_DIR_end(&d);
return ret;
}
static int add_uris_recursive(STACK_OF(X509_NAME) *stack,
const char *uri, int depth)
{
int ok = 1;
OSSL_STORE_CTX *ctx = NULL;
X509 *x = NULL;
X509_NAME *xn = NULL;
if ((ctx = OSSL_STORE_open(uri, NULL, NULL, NULL, NULL)) == NULL)
goto err;
while (!OSSL_STORE_eof(ctx) && !OSSL_STORE_error(ctx)) {
OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
int infotype = info == 0 ? 0 : OSSL_STORE_INFO_get_type(info);
if (info == NULL)
continue;
if (infotype == OSSL_STORE_INFO_NAME) {
/*
* This is an entry in the "directory" represented by the current
* uri. if |depth| allows, dive into it.
*/
if (depth > 0)
ok = add_uris_recursive(stack, OSSL_STORE_INFO_get0_NAME(info),
depth - 1);
} else if (infotype == OSSL_STORE_INFO_CERT) {
if ((x = OSSL_STORE_INFO_get0_CERT(info)) == NULL
|| (xn = X509_get_subject_name(x)) == NULL
|| (xn = X509_NAME_dup(xn)) == NULL)
goto err;
if (sk_X509_NAME_find(stack, xn) >= 0) {
/* Duplicate. */
X509_NAME_free(xn);
} else if (!sk_X509_NAME_push(stack, xn)) {
X509_NAME_free(xn);
goto err;
}
}
OSSL_STORE_INFO_free(info);
}
ERR_clear_error();
goto done;
err:
ok = 0;
done:
OSSL_STORE_close(ctx);
return ok;
}
int SSL_add_store_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
const char *store)
{
int (*oldcmp) (const X509_NAME *const *a, const X509_NAME *const *b)
= sk_X509_NAME_set_cmp_func(stack, xname_sk_cmp);
int ret = add_uris_recursive(stack, store, 1);
(void)sk_X509_NAME_set_cmp_func(stack, oldcmp);
return ret;
}
/* Build a certificate chain for current certificate */
int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
{
CERT *c = s ? s->cert : ctx->cert;
CERT_PKEY *cpk = c->key;
X509_STORE *chain_store = NULL;
X509_STORE_CTX *xs_ctx = NULL;
STACK_OF(X509) *chain = NULL, *untrusted = NULL;
X509 *x;
SSL_CTX *real_ctx = (s == NULL) ? ctx : s->ctx;
int i, rv = 0;
if (!cpk->x509) {
ERR_raise(ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_SET);
goto err;
}
/* Rearranging and check the chain: add everything to a store */
if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) {
chain_store = X509_STORE_new();
if (chain_store == NULL)
goto err;
for (i = 0; i < sk_X509_num(cpk->chain); i++) {
x = sk_X509_value(cpk->chain, i);
if (!X509_STORE_add_cert(chain_store, x))
goto err;
}
/* Add EE cert too: it might be self signed */
if (!X509_STORE_add_cert(chain_store, cpk->x509))
goto err;
} else {
if (c->chain_store)
chain_store = c->chain_store;
else if (s)
chain_store = s->ctx->cert_store;
else
chain_store = ctx->cert_store;
if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED)
untrusted = cpk->chain;
}
xs_ctx = X509_STORE_CTX_new_ex(real_ctx->libctx, real_ctx->propq);
if (xs_ctx == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!X509_STORE_CTX_init(xs_ctx, chain_store, cpk->x509, untrusted)) {
ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB);
goto err;
}
/* Set suite B flags if needed */
X509_STORE_CTX_set_flags(xs_ctx,
c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS);
i = X509_verify_cert(xs_ctx);
if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) {
if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR)
ERR_clear_error();
i = 1;
rv = 2;
}
if (i > 0)
chain = X509_STORE_CTX_get1_chain(xs_ctx);
if (i <= 0) {
i = X509_STORE_CTX_get_error(xs_ctx);
ERR_raise_data(ERR_LIB_SSL, SSL_R_CERTIFICATE_VERIFY_FAILED,
"Verify error:%s", X509_verify_cert_error_string(i));
goto err;
}
/* Remove EE certificate from chain */
x = sk_X509_shift(chain);
X509_free(x);
if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) {
if (sk_X509_num(chain) > 0) {
/* See if last cert is self signed */
x = sk_X509_value(chain, sk_X509_num(chain) - 1);
if (X509_get_extension_flags(x) & EXFLAG_SS) {
x = sk_X509_pop(chain);
X509_free(x);
}
}
}
/*
* Check security level of all CA certificates: EE will have been checked
* already.
*/
for (i = 0; i < sk_X509_num(chain); i++) {
x = sk_X509_value(chain, i);
rv = ssl_security_cert(s, ctx, x, 0, 0);
if (rv != 1) {
ERR_raise(ERR_LIB_SSL, rv);
sk_X509_pop_free(chain, X509_free);
rv = 0;
goto err;
}
}
sk_X509_pop_free(cpk->chain, X509_free);
cpk->chain = chain;
if (rv == 0)
rv = 1;
err:
if (flags & SSL_BUILD_CHAIN_FLAG_CHECK)
X509_STORE_free(chain_store);
X509_STORE_CTX_free(xs_ctx);
return rv;
}
int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref)
{
X509_STORE **pstore;
if (chain)
pstore = &c->chain_store;
else
pstore = &c->verify_store;
X509_STORE_free(*pstore);
*pstore = store;
if (ref && store)
X509_STORE_up_ref(store);
return 1;
}
int ssl_cert_get_cert_store(CERT *c, X509_STORE **pstore, int chain)
{
*pstore = (chain ? c->chain_store : c->verify_store);
return 1;
}
int ssl_get_security_level_bits(const SSL *s, const SSL_CTX *ctx, int *levelp)
{
int level;
/*
* note that there's a corresponding minbits_table
* in crypto/x509/x509_vfy.c that's used for checking the security level
* of RSA and DSA keys
*/
static const int minbits_table[5 + 1] = { 0, 80, 112, 128, 192, 256 };
if (ctx != NULL)
level = SSL_CTX_get_security_level(ctx);
else
level = SSL_get_security_level(s);
if (level > 5)
level = 5;
else if (level < 0)
level = 0;
if (levelp != NULL)
*levelp = level;
return minbits_table[level];
}
static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx,
int op, int bits, int nid, void *other,
void *ex)
{
int level, minbits, pfs_mask;
minbits = ssl_get_security_level_bits(s, ctx, &level);
if (level == 0) {
/*
* No EDH keys weaker than 1024-bits even at level 0, otherwise,
* anything goes.
*/
if (op == SSL_SECOP_TMP_DH && bits < 80)
return 0;
return 1;
}
switch (op) {
case SSL_SECOP_CIPHER_SUPPORTED:
case SSL_SECOP_CIPHER_SHARED:
case SSL_SECOP_CIPHER_CHECK:
{
const SSL_CIPHER *c = other;
/* No ciphers below security level */
if (bits < minbits)
return 0;
/* No unauthenticated ciphersuites */
if (c->algorithm_auth & SSL_aNULL)
return 0;
/* No MD5 mac ciphersuites */
if (c->algorithm_mac & SSL_MD5)
return 0;
/* SHA1 HMAC is 160 bits of security */
if (minbits > 160 && c->algorithm_mac & SSL_SHA1)
return 0;
/* Level 2: no RC4 */
if (level >= 2 && c->algorithm_enc == SSL_RC4)
return 0;
/* Level 3: forward secure ciphersuites only */
pfs_mask = SSL_kDHE | SSL_kECDHE | SSL_kDHEPSK | SSL_kECDHEPSK;
if (level >= 3 && c->min_tls != TLS1_3_VERSION &&
!(c->algorithm_mkey & pfs_mask))
return 0;
break;
}
case SSL_SECOP_VERSION:
if (!SSL_IS_DTLS(s)) {
/* SSLv3 not allowed at level 2 */
if (nid <= SSL3_VERSION && level >= 2)
return 0;
/* TLS v1.1 and above only for level 3 */
if (nid <= TLS1_VERSION && level >= 3)
return 0;
/* TLS v1.2 only for level 4 and above */
if (nid <= TLS1_1_VERSION && level >= 4)
return 0;
} else {
/* DTLS v1.2 only for level 4 and above */
if (DTLS_VERSION_LT(nid, DTLS1_2_VERSION) && level >= 4)
return 0;
}
break;
case SSL_SECOP_COMPRESSION:
if (level >= 2)
return 0;
break;
case SSL_SECOP_TICKET:
if (level >= 3)
return 0;
break;
default:
if (bits < minbits)
return 0;
}
return 1;
}
int ssl_security(const SSL *s, int op, int bits, int nid, void *other)
{
return s->cert->sec_cb(s, NULL, op, bits, nid, other, s->cert->sec_ex);
}
int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, void *other)
{
return ctx->cert->sec_cb(NULL, ctx, op, bits, nid, other,
ctx->cert->sec_ex);
}
int ssl_cert_lookup_by_nid(int nid, size_t *pidx)
{
size_t i;
for (i = 0; i < OSSL_NELEM(ssl_cert_info); i++) {
if (ssl_cert_info[i].nid == nid) {
*pidx = i;
return 1;
}
}
return 0;
}
const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx)
{
size_t i;
for (i = 0; i < OSSL_NELEM(ssl_cert_info); i++) {
const SSL_CERT_LOOKUP *tmp_lu = &ssl_cert_info[i];
if (EVP_PKEY_is_a(pk, OBJ_nid2sn(tmp_lu->nid))
|| EVP_PKEY_is_a(pk, OBJ_nid2ln(tmp_lu->nid))) {
if (pidx != NULL)
*pidx = i;
return tmp_lu;
}
}
return NULL;
}
const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx)
{
if (idx >= OSSL_NELEM(ssl_cert_info))
return NULL;
return &ssl_cert_info[idx];
}
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index 68b57a532bfe..c322a11d9c52 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -1,1394 +1,1395 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. 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
*/
#if defined(__TANDEM) && defined(_SPT_MODEL_)
# include <spthread.h>
# include <spt_extensions.h> /* timeval */
#endif
#include <stdio.h>
#include <openssl/rand.h>
#include <openssl/engine.h>
#include "internal/refcount.h"
#include "internal/cryptlib.h"
#include "ssl_local.h"
#include "statem/statem_local.h"
static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s);
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
DEFINE_STACK_OF(SSL_SESSION)
__owur static int sess_timedout(time_t t, SSL_SESSION *ss)
{
/* if timeout overflowed, it can never timeout! */
if (ss->timeout_ovf)
return 0;
return t > ss->calc_timeout;
}
/*
* Returns -1/0/+1 as other XXXcmp-type functions
* Takes overflow of calculated timeout into consideration
*/
__owur static int timeoutcmp(SSL_SESSION *a, SSL_SESSION *b)
{
/* if only one overflowed, then it is greater */
if (a->timeout_ovf && !b->timeout_ovf)
return 1;
if (!a->timeout_ovf && b->timeout_ovf)
return -1;
/* No overflow, or both overflowed, so straight compare is safe */
if (a->calc_timeout < b->calc_timeout)
return -1;
if (a->calc_timeout > b->calc_timeout)
return 1;
return 0;
}
/*
* Calculates effective timeout, saving overflow state
* Locking must be done by the caller of this function
*/
void ssl_session_calculate_timeout(SSL_SESSION *ss)
{
/* Force positive timeout */
if (ss->timeout < 0)
ss->timeout = 0;
ss->calc_timeout = ss->time + ss->timeout;
/*
* |timeout| is always zero or positive, so the check for
* overflow only needs to consider if |time| is positive
*/
ss->timeout_ovf = ss->time > 0 && ss->calc_timeout < ss->time;
/*
* N.B. Realistic overflow can only occur in our lifetimes on a
* 32-bit machine in January 2038.
* However, There are no controls to limit the |timeout|
* value, except to keep it positive.
*/
}
/*
* SSL_get_session() and SSL_get1_session() are problematic in TLS1.3 because,
* unlike in earlier protocol versions, the session ticket may not have been
* sent yet even though a handshake has finished. The session ticket data could
* come in sometime later...or even change if multiple session ticket messages
* are sent from the server. The preferred way for applications to obtain
* a resumable session is to use SSL_CTX_sess_set_new_cb().
*/
SSL_SESSION *SSL_get_session(const SSL *ssl)
/* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
{
return ssl->session;
}
SSL_SESSION *SSL_get1_session(SSL *ssl)
/* variant of SSL_get_session: caller really gets something */
{
SSL_SESSION *sess;
/*
* Need to lock this all up rather than just use CRYPTO_add so that
* somebody doesn't free ssl->session between when we check it's non-null
* and when we up the reference count.
*/
if (!CRYPTO_THREAD_read_lock(ssl->lock))
return NULL;
sess = ssl->session;
if (sess)
SSL_SESSION_up_ref(sess);
CRYPTO_THREAD_unlock(ssl->lock);
return sess;
}
int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg)
{
return CRYPTO_set_ex_data(&s->ex_data, idx, arg);
}
void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx)
{
return CRYPTO_get_ex_data(&s->ex_data, idx);
}
SSL_SESSION *SSL_SESSION_new(void)
{
SSL_SESSION *ss;
if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL))
return NULL;
ss = OPENSSL_zalloc(sizeof(*ss));
if (ss == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
ss->references = 1;
ss->timeout = 60 * 5 + 4; /* 5 minute timeout by default */
ss->time = time(NULL);
ssl_session_calculate_timeout(ss);
ss->lock = CRYPTO_THREAD_lock_new();
if (ss->lock == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ss);
return NULL;
}
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data)) {
CRYPTO_THREAD_lock_free(ss->lock);
OPENSSL_free(ss);
return NULL;
}
return ss;
}
SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src)
{
return ssl_session_dup(src, 1);
}
/*
* Create a new SSL_SESSION and duplicate the contents of |src| into it. If
* ticket == 0 then no ticket information is duplicated, otherwise it is.
*/
SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket)
{
SSL_SESSION *dest;
dest = OPENSSL_malloc(sizeof(*dest));
if (dest == NULL) {
goto err;
}
memcpy(dest, src, sizeof(*dest));
/*
* Set the various pointers to NULL so that we can call SSL_SESSION_free in
* the case of an error whilst halfway through constructing dest
*/
#ifndef OPENSSL_NO_PSK
dest->psk_identity_hint = NULL;
dest->psk_identity = NULL;
#endif
dest->ext.hostname = NULL;
dest->ext.tick = NULL;
dest->ext.alpn_selected = NULL;
#ifndef OPENSSL_NO_SRP
dest->srp_username = NULL;
#endif
dest->peer_chain = NULL;
dest->peer = NULL;
dest->ticket_appdata = NULL;
memset(&dest->ex_data, 0, sizeof(dest->ex_data));
- /* We deliberately don't copy the prev and next pointers */
+ /* As the copy is not in the cache, we remove the associated pointers */
dest->prev = NULL;
dest->next = NULL;
+ dest->owner = NULL;
dest->references = 1;
dest->lock = CRYPTO_THREAD_lock_new();
if (dest->lock == NULL)
goto err;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, dest, &dest->ex_data))
goto err;
if (src->peer != NULL) {
if (!X509_up_ref(src->peer))
goto err;
dest->peer = src->peer;
}
if (src->peer_chain != NULL) {
dest->peer_chain = X509_chain_up_ref(src->peer_chain);
if (dest->peer_chain == NULL)
goto err;
}
#ifndef OPENSSL_NO_PSK
if (src->psk_identity_hint) {
dest->psk_identity_hint = OPENSSL_strdup(src->psk_identity_hint);
if (dest->psk_identity_hint == NULL) {
goto err;
}
}
if (src->psk_identity) {
dest->psk_identity = OPENSSL_strdup(src->psk_identity);
if (dest->psk_identity == NULL) {
goto err;
}
}
#endif
if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
&dest->ex_data, &src->ex_data)) {
goto err;
}
if (src->ext.hostname) {
dest->ext.hostname = OPENSSL_strdup(src->ext.hostname);
if (dest->ext.hostname == NULL) {
goto err;
}
}
if (ticket != 0 && src->ext.tick != NULL) {
dest->ext.tick =
OPENSSL_memdup(src->ext.tick, src->ext.ticklen);
if (dest->ext.tick == NULL)
goto err;
} else {
dest->ext.tick_lifetime_hint = 0;
dest->ext.ticklen = 0;
}
if (src->ext.alpn_selected != NULL) {
dest->ext.alpn_selected = OPENSSL_memdup(src->ext.alpn_selected,
src->ext.alpn_selected_len);
if (dest->ext.alpn_selected == NULL)
goto err;
}
#ifndef OPENSSL_NO_SRP
if (src->srp_username) {
dest->srp_username = OPENSSL_strdup(src->srp_username);
if (dest->srp_username == NULL) {
goto err;
}
}
#endif
if (src->ticket_appdata != NULL) {
dest->ticket_appdata =
OPENSSL_memdup(src->ticket_appdata, src->ticket_appdata_len);
if (dest->ticket_appdata == NULL)
goto err;
}
return dest;
err:
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
SSL_SESSION_free(dest);
return NULL;
}
const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
{
if (len)
*len = (unsigned int)s->session_id_length;
return s->session_id;
}
const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s,
unsigned int *len)
{
if (len != NULL)
*len = (unsigned int)s->sid_ctx_length;
return s->sid_ctx;
}
unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s)
{
return s->compress_meth;
}
/*
* SSLv3/TLSv1 has 32 bytes (256 bits) of session ID space. As such, filling
* the ID with random junk repeatedly until we have no conflict is going to
* complete in one iteration pretty much "most" of the time (btw:
* understatement). So, if it takes us 10 iterations and we still can't avoid
* a conflict - well that's a reasonable point to call it quits. Either the
* RAND code is broken or someone is trying to open roughly very close to
* 2^256 SSL sessions to our server. How you might store that many sessions
* is perhaps a more interesting question ...
*/
#define MAX_SESS_ID_ATTEMPTS 10
static int def_generate_session_id(SSL *ssl, unsigned char *id,
unsigned int *id_len)
{
unsigned int retry = 0;
do
if (RAND_bytes_ex(ssl->ctx->libctx, id, *id_len, 0) <= 0)
return 0;
while (SSL_has_matching_session_id(ssl, id, *id_len) &&
(++retry < MAX_SESS_ID_ATTEMPTS)) ;
if (retry < MAX_SESS_ID_ATTEMPTS)
return 1;
/* else - woops a session_id match */
/*
* XXX We should also check the external cache -- but the probability of
* a collision is negligible, and we could not prevent the concurrent
* creation of sessions with identical IDs since we currently don't have
* means to atomically check whether a session ID already exists and make
* a reservation for it if it does not (this problem applies to the
* internal cache as well).
*/
return 0;
}
int ssl_generate_session_id(SSL *s, SSL_SESSION *ss)
{
unsigned int tmp;
GEN_SESSION_CB cb = def_generate_session_id;
switch (s->version) {
case SSL3_VERSION:
case TLS1_VERSION:
case TLS1_1_VERSION:
case TLS1_2_VERSION:
case TLS1_3_VERSION:
case DTLS1_BAD_VER:
case DTLS1_VERSION:
case DTLS1_2_VERSION:
ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
break;
default:
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_UNSUPPORTED_SSL_VERSION);
return 0;
}
/*-
* If RFC5077 ticket, use empty session ID (as server).
* Note that:
* (a) ssl_get_prev_session() does lookahead into the
* ClientHello extensions to find the session ticket.
* When ssl_get_prev_session() fails, statem_srvr.c calls
* ssl_get_new_session() in tls_process_client_hello().
* At that point, it has not yet parsed the extensions,
* however, because of the lookahead, it already knows
* whether a ticket is expected or not.
*
* (b) statem_clnt.c calls ssl_get_new_session() before parsing
* ServerHello extensions, and before recording the session
* ID received from the server, so this block is a noop.
*/
if (s->ext.ticket_expected) {
ss->session_id_length = 0;
return 1;
}
/* Choose which callback will set the session ID */
if (!CRYPTO_THREAD_read_lock(s->lock))
return 0;
if (!CRYPTO_THREAD_read_lock(s->session_ctx->lock)) {
CRYPTO_THREAD_unlock(s->lock);
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
return 0;
}
if (s->generate_session_id)
cb = s->generate_session_id;
else if (s->session_ctx->generate_session_id)
cb = s->session_ctx->generate_session_id;
CRYPTO_THREAD_unlock(s->session_ctx->lock);
CRYPTO_THREAD_unlock(s->lock);
/* Choose a session ID */
memset(ss->session_id, 0, ss->session_id_length);
tmp = (int)ss->session_id_length;
if (!cb(s, ss->session_id, &tmp)) {
/* The callback failed */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
return 0;
}
/*
* Don't allow the callback to set the session length to zero. nor
* set it higher than it was.
*/
if (tmp == 0 || tmp > ss->session_id_length) {
/* The callback set an illegal length */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
return 0;
}
ss->session_id_length = tmp;
/* Finally, check for a conflict */
if (SSL_has_matching_session_id(s, ss->session_id,
(unsigned int)ss->session_id_length)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_SSL_SESSION_ID_CONFLICT);
return 0;
}
return 1;
}
int ssl_get_new_session(SSL *s, int session)
{
/* This gets used by clients and servers. */
SSL_SESSION *ss = NULL;
if ((ss = SSL_SESSION_new()) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
/* If the context has a default timeout, use it */
if (s->session_ctx->session_timeout == 0)
ss->timeout = SSL_get_default_timeout(s);
else
ss->timeout = s->session_ctx->session_timeout;
ssl_session_calculate_timeout(ss);
SSL_SESSION_free(s->session);
s->session = NULL;
if (session) {
if (SSL_IS_TLS13(s)) {
/*
* We generate the session id while constructing the
* NewSessionTicket in TLSv1.3.
*/
ss->session_id_length = 0;
} else if (!ssl_generate_session_id(s, ss)) {
/* SSLfatal() already called */
SSL_SESSION_free(ss);
return 0;
}
} else {
ss->session_id_length = 0;
}
if (s->sid_ctx_length > sizeof(ss->sid_ctx)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
SSL_SESSION_free(ss);
return 0;
}
memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length);
ss->sid_ctx_length = s->sid_ctx_length;
s->session = ss;
ss->ssl_version = s->version;
ss->verify_result = X509_V_OK;
/* If client supports extended master secret set it in session */
if (s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS)
ss->flags |= SSL_SESS_FLAG_EXTMS;
return 1;
}
SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id,
size_t sess_id_len)
{
SSL_SESSION *ret = NULL;
if ((s->session_ctx->session_cache_mode
& SSL_SESS_CACHE_NO_INTERNAL_LOOKUP) == 0) {
SSL_SESSION data;
data.ssl_version = s->version;
if (!ossl_assert(sess_id_len <= SSL_MAX_SSL_SESSION_ID_LENGTH))
return NULL;
memcpy(data.session_id, sess_id, sess_id_len);
data.session_id_length = sess_id_len;
if (!CRYPTO_THREAD_read_lock(s->session_ctx->lock))
return NULL;
ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data);
if (ret != NULL) {
/* don't allow other threads to steal it: */
SSL_SESSION_up_ref(ret);
}
CRYPTO_THREAD_unlock(s->session_ctx->lock);
if (ret == NULL)
ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_miss);
}
if (ret == NULL && s->session_ctx->get_session_cb != NULL) {
int copy = 1;
ret = s->session_ctx->get_session_cb(s, sess_id, sess_id_len, &copy);
if (ret != NULL) {
ssl_tsan_counter(s->session_ctx,
&s->session_ctx->stats.sess_cb_hit);
/*
* Increment reference count now if the session callback asks us
* to do so (note that if the session structures returned by the
* callback are shared between threads, it must handle the
* reference count itself [i.e. copy == 0], or things won't be
* thread-safe).
*/
if (copy)
SSL_SESSION_up_ref(ret);
/*
* Add the externally cached session to the internal cache as
* well if and only if we are supposed to.
*/
if ((s->session_ctx->session_cache_mode &
SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0) {
/*
* Either return value of SSL_CTX_add_session should not
* interrupt the session resumption process. The return
* value is intentionally ignored.
*/
(void)SSL_CTX_add_session(s->session_ctx, ret);
}
}
}
return ret;
}
/*-
* ssl_get_prev attempts to find an SSL_SESSION to be used to resume this
* connection. It is only called by servers.
*
* hello: The parsed ClientHello data
*
* Returns:
* -1: fatal error
* 0: no session found
* 1: a session may have been found.
*
* Side effects:
* - If a session is found then s->session is pointed at it (after freeing an
* existing session if need be) and s->verify_result is set from the session.
* - Both for new and resumed sessions, s->ext.ticket_expected is set to 1
* if the server should issue a new session ticket (to 0 otherwise).
*/
int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
{
/* This is used only by servers. */
SSL_SESSION *ret = NULL;
int fatal = 0;
int try_session_cache = 0;
SSL_TICKET_STATUS r;
if (SSL_IS_TLS13(s)) {
/*
* By default we will send a new ticket. This can be overridden in the
* ticket processing.
*/
s->ext.ticket_expected = 1;
if (!tls_parse_extension(s, TLSEXT_IDX_psk_kex_modes,
SSL_EXT_CLIENT_HELLO, hello->pre_proc_exts,
NULL, 0)
|| !tls_parse_extension(s, TLSEXT_IDX_psk, SSL_EXT_CLIENT_HELLO,
hello->pre_proc_exts, NULL, 0))
return -1;
ret = s->session;
} else {
/* sets s->ext.ticket_expected */
r = tls_get_ticket_from_client(s, hello, &ret);
switch (r) {
case SSL_TICKET_FATAL_ERR_MALLOC:
case SSL_TICKET_FATAL_ERR_OTHER:
fatal = 1;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
case SSL_TICKET_NONE:
case SSL_TICKET_EMPTY:
if (hello->session_id_len > 0) {
try_session_cache = 1;
ret = lookup_sess_in_cache(s, hello->session_id,
hello->session_id_len);
}
break;
case SSL_TICKET_NO_DECRYPT:
case SSL_TICKET_SUCCESS:
case SSL_TICKET_SUCCESS_RENEW:
break;
}
}
if (ret == NULL)
goto err;
/* Now ret is non-NULL and we own one of its reference counts. */
/* Check TLS version consistency */
if (ret->ssl_version != s->version)
goto err;
if (ret->sid_ctx_length != s->sid_ctx_length
|| memcmp(ret->sid_ctx, s->sid_ctx, ret->sid_ctx_length)) {
/*
* We have the session requested by the client, but we don't want to
* use it in this context.
*/
goto err; /* treat like cache miss */
}
if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) {
/*
* We can't be sure if this session is being used out of context,
* which is especially important for SSL_VERIFY_PEER. The application
* should have used SSL[_CTX]_set_session_id_context. For this error
* case, we generate an error instead of treating the event like a
* cache miss (otherwise it would be easy for applications to
* effectively disable the session cache by accident without anyone
* noticing).
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
fatal = 1;
goto err;
}
if (sess_timedout(time(NULL), ret)) {
ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_timeout);
if (try_session_cache) {
/* session was from the cache, so remove it */
SSL_CTX_remove_session(s->session_ctx, ret);
}
goto err;
}
/* Check extended master secret extension consistency */
if (ret->flags & SSL_SESS_FLAG_EXTMS) {
/* If old session includes extms, but new does not: abort handshake */
if (!(s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_INCONSISTENT_EXTMS);
fatal = 1;
goto err;
}
} else if (s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) {
/* If new session includes extms, but old does not: do not resume */
goto err;
}
if (!SSL_IS_TLS13(s)) {
/* We already did this for TLS1.3 */
SSL_SESSION_free(s->session);
s->session = ret;
}
ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_hit);
s->verify_result = s->session->verify_result;
return 1;
err:
if (ret != NULL) {
SSL_SESSION_free(ret);
/* In TLSv1.3 s->session was already set to ret, so we NULL it out */
if (SSL_IS_TLS13(s))
s->session = NULL;
if (!try_session_cache) {
/*
* The session was from a ticket, so we should issue a ticket for
* the new session
*/
s->ext.ticket_expected = 1;
}
}
if (fatal)
return -1;
return 0;
}
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
{
int ret = 0;
SSL_SESSION *s;
/*
* add just 1 reference count for the SSL_CTX's session cache even though
* it has two ways of access: each session is in a doubly linked list and
* an lhash
*/
SSL_SESSION_up_ref(c);
/*
* if session c is in already in cache, we take back the increment later
*/
if (!CRYPTO_THREAD_write_lock(ctx->lock)) {
SSL_SESSION_free(c);
return 0;
}
s = lh_SSL_SESSION_insert(ctx->sessions, c);
/*
* s != NULL iff we already had a session with the given PID. In this
* case, s == c should hold (then we did not really modify
* ctx->sessions), or we're in trouble.
*/
if (s != NULL && s != c) {
/* We *are* in trouble ... */
SSL_SESSION_list_remove(ctx, s);
SSL_SESSION_free(s);
/*
* ... so pretend the other session did not exist in cache (we cannot
* handle two SSL_SESSION structures with identical session ID in the
* same cache, which could happen e.g. when two threads concurrently
* obtain the same session from an external cache)
*/
s = NULL;
} else if (s == NULL &&
lh_SSL_SESSION_retrieve(ctx->sessions, c) == NULL) {
/* s == NULL can also mean OOM error in lh_SSL_SESSION_insert ... */
/*
* ... so take back the extra reference and also don't add
* the session to the SSL_SESSION_list at this time
*/
s = c;
}
/* Adjust last used time, and add back into the cache at the appropriate spot */
if (ctx->session_cache_mode & SSL_SESS_CACHE_UPDATE_TIME) {
c->time = time(NULL);
ssl_session_calculate_timeout(c);
}
if (s == NULL) {
/*
* new cache entry -- remove old ones if cache has become too large
* delete cache entry *before* add, so we don't remove the one we're adding!
*/
ret = 1;
if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
while (SSL_CTX_sess_number(ctx) >= SSL_CTX_sess_get_cache_size(ctx)) {
if (!remove_session_lock(ctx, ctx->session_cache_tail, 0))
break;
else
ssl_tsan_counter(ctx, &ctx->stats.sess_cache_full);
}
}
}
SSL_SESSION_list_add(ctx, c);
if (s != NULL) {
/*
* existing cache entry -- decrement previously incremented reference
* count because it already takes into account the cache
*/
SSL_SESSION_free(s); /* s == c */
ret = 0;
}
CRYPTO_THREAD_unlock(ctx->lock);
return ret;
}
int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c)
{
return remove_session_lock(ctx, c, 1);
}
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck)
{
SSL_SESSION *r;
int ret = 0;
if ((c != NULL) && (c->session_id_length != 0)) {
if (lck) {
if (!CRYPTO_THREAD_write_lock(ctx->lock))
return 0;
}
if ((r = lh_SSL_SESSION_retrieve(ctx->sessions, c)) != NULL) {
ret = 1;
r = lh_SSL_SESSION_delete(ctx->sessions, r);
SSL_SESSION_list_remove(ctx, r);
}
c->not_resumable = 1;
if (lck)
CRYPTO_THREAD_unlock(ctx->lock);
if (ctx->remove_session_cb != NULL)
ctx->remove_session_cb(ctx, c);
if (ret)
SSL_SESSION_free(r);
}
return ret;
}
void SSL_SESSION_free(SSL_SESSION *ss)
{
int i;
if (ss == NULL)
return;
CRYPTO_DOWN_REF(&ss->references, &i, ss->lock);
REF_PRINT_COUNT("SSL_SESSION", ss);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
OPENSSL_cleanse(ss->master_key, sizeof(ss->master_key));
OPENSSL_cleanse(ss->session_id, sizeof(ss->session_id));
X509_free(ss->peer);
sk_X509_pop_free(ss->peer_chain, X509_free);
OPENSSL_free(ss->ext.hostname);
OPENSSL_free(ss->ext.tick);
#ifndef OPENSSL_NO_PSK
OPENSSL_free(ss->psk_identity_hint);
OPENSSL_free(ss->psk_identity);
#endif
#ifndef OPENSSL_NO_SRP
OPENSSL_free(ss->srp_username);
#endif
OPENSSL_free(ss->ext.alpn_selected);
OPENSSL_free(ss->ticket_appdata);
CRYPTO_THREAD_lock_free(ss->lock);
OPENSSL_clear_free(ss, sizeof(*ss));
}
int SSL_SESSION_up_ref(SSL_SESSION *ss)
{
int i;
if (CRYPTO_UP_REF(&ss->references, &i, ss->lock) <= 0)
return 0;
REF_PRINT_COUNT("SSL_SESSION", ss);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}
int SSL_set_session(SSL *s, SSL_SESSION *session)
{
ssl_clear_bad_session(s);
if (s->ctx->method != s->method) {
if (!SSL_set_ssl_method(s, s->ctx->method))
return 0;
}
if (session != NULL) {
SSL_SESSION_up_ref(session);
s->verify_result = session->verify_result;
}
SSL_SESSION_free(s->session);
s->session = session;
return 1;
}
int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid,
unsigned int sid_len)
{
if (sid_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
ERR_raise(ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_TOO_LONG);
return 0;
}
s->session_id_length = sid_len;
if (sid != s->session_id)
memcpy(s->session_id, sid, sid_len);
return 1;
}
long SSL_SESSION_set_timeout(SSL_SESSION *s, long t)
{
time_t new_timeout = (time_t)t;
if (s == NULL || t < 0)
return 0;
if (s->owner != NULL) {
if (!CRYPTO_THREAD_write_lock(s->owner->lock))
return 0;
s->timeout = new_timeout;
ssl_session_calculate_timeout(s);
SSL_SESSION_list_add(s->owner, s);
CRYPTO_THREAD_unlock(s->owner->lock);
} else {
s->timeout = new_timeout;
ssl_session_calculate_timeout(s);
}
return 1;
}
long SSL_SESSION_get_timeout(const SSL_SESSION *s)
{
if (s == NULL)
return 0;
return (long)s->timeout;
}
long SSL_SESSION_get_time(const SSL_SESSION *s)
{
if (s == NULL)
return 0;
return (long)s->time;
}
long SSL_SESSION_set_time(SSL_SESSION *s, long t)
{
time_t new_time = (time_t)t;
if (s == NULL)
return 0;
if (s->owner != NULL) {
if (!CRYPTO_THREAD_write_lock(s->owner->lock))
return 0;
s->time = new_time;
ssl_session_calculate_timeout(s);
SSL_SESSION_list_add(s->owner, s);
CRYPTO_THREAD_unlock(s->owner->lock);
} else {
s->time = new_time;
ssl_session_calculate_timeout(s);
}
return t;
}
int SSL_SESSION_get_protocol_version(const SSL_SESSION *s)
{
return s->ssl_version;
}
int SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version)
{
s->ssl_version = version;
return 1;
}
const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s)
{
return s->cipher;
}
int SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher)
{
s->cipher = cipher;
return 1;
}
const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s)
{
return s->ext.hostname;
}
int SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname)
{
OPENSSL_free(s->ext.hostname);
if (hostname == NULL) {
s->ext.hostname = NULL;
return 1;
}
s->ext.hostname = OPENSSL_strdup(hostname);
return s->ext.hostname != NULL;
}
int SSL_SESSION_has_ticket(const SSL_SESSION *s)
{
return (s->ext.ticklen > 0) ? 1 : 0;
}
unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s)
{
return s->ext.tick_lifetime_hint;
}
void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick,
size_t *len)
{
*len = s->ext.ticklen;
if (tick != NULL)
*tick = s->ext.tick;
}
uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s)
{
return s->ext.max_early_data;
}
int SSL_SESSION_set_max_early_data(SSL_SESSION *s, uint32_t max_early_data)
{
s->ext.max_early_data = max_early_data;
return 1;
}
void SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s,
const unsigned char **alpn,
size_t *len)
{
*alpn = s->ext.alpn_selected;
*len = s->ext.alpn_selected_len;
}
int SSL_SESSION_set1_alpn_selected(SSL_SESSION *s, const unsigned char *alpn,
size_t len)
{
OPENSSL_free(s->ext.alpn_selected);
if (alpn == NULL || len == 0) {
s->ext.alpn_selected = NULL;
s->ext.alpn_selected_len = 0;
return 1;
}
s->ext.alpn_selected = OPENSSL_memdup(alpn, len);
if (s->ext.alpn_selected == NULL) {
s->ext.alpn_selected_len = 0;
return 0;
}
s->ext.alpn_selected_len = len;
return 1;
}
X509 *SSL_SESSION_get0_peer(SSL_SESSION *s)
{
return s->peer;
}
int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx,
unsigned int sid_ctx_len)
{
if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
ERR_raise(ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
return 0;
}
s->sid_ctx_length = sid_ctx_len;
if (sid_ctx != s->sid_ctx)
memcpy(s->sid_ctx, sid_ctx, sid_ctx_len);
return 1;
}
int SSL_SESSION_is_resumable(const SSL_SESSION *s)
{
/*
* In the case of EAP-FAST, we can have a pre-shared "ticket" without a
* session ID.
*/
return !s->not_resumable
&& (s->session_id_length > 0 || s->ext.ticklen > 0);
}
long SSL_CTX_set_timeout(SSL_CTX *s, long t)
{
long l;
if (s == NULL)
return 0;
l = s->session_timeout;
s->session_timeout = t;
return l;
}
long SSL_CTX_get_timeout(const SSL_CTX *s)
{
if (s == NULL)
return 0;
return s->session_timeout;
}
int SSL_set_session_secret_cb(SSL *s,
tls_session_secret_cb_fn tls_session_secret_cb,
void *arg)
{
if (s == NULL)
return 0;
s->ext.session_secret_cb = tls_session_secret_cb;
s->ext.session_secret_cb_arg = arg;
return 1;
}
int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
void *arg)
{
if (s == NULL)
return 0;
s->ext.session_ticket_cb = cb;
s->ext.session_ticket_cb_arg = arg;
return 1;
}
int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
{
if (s->version >= TLS1_VERSION) {
OPENSSL_free(s->ext.session_ticket);
s->ext.session_ticket = NULL;
s->ext.session_ticket =
OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
if (s->ext.session_ticket == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (ext_data != NULL) {
s->ext.session_ticket->length = ext_len;
s->ext.session_ticket->data = s->ext.session_ticket + 1;
memcpy(s->ext.session_ticket->data, ext_data, ext_len);
} else {
s->ext.session_ticket->length = 0;
s->ext.session_ticket->data = NULL;
}
return 1;
}
return 0;
}
void SSL_CTX_flush_sessions(SSL_CTX *s, long t)
{
STACK_OF(SSL_SESSION) *sk;
SSL_SESSION *current;
unsigned long i;
if (!CRYPTO_THREAD_write_lock(s->lock))
return;
sk = sk_SSL_SESSION_new_null();
i = lh_SSL_SESSION_get_down_load(s->sessions);
lh_SSL_SESSION_set_down_load(s->sessions, 0);
/*
* Iterate over the list from the back (oldest), and stop
* when a session can no longer be removed.
* Add the session to a temporary list to be freed outside
* the SSL_CTX lock.
* But still do the remove_session_cb() within the lock.
*/
while (s->session_cache_tail != NULL) {
current = s->session_cache_tail;
if (t == 0 || sess_timedout((time_t)t, current)) {
lh_SSL_SESSION_delete(s->sessions, current);
SSL_SESSION_list_remove(s, current);
current->not_resumable = 1;
if (s->remove_session_cb != NULL)
s->remove_session_cb(s, current);
/*
* Throw the session on a stack, it's entirely plausible
* that while freeing outside the critical section, the
* session could be re-added, so avoid using the next/prev
* pointers. If the stack failed to create, or the session
* couldn't be put on the stack, just free it here
*/
if (sk == NULL || !sk_SSL_SESSION_push(sk, current))
SSL_SESSION_free(current);
} else {
break;
}
}
lh_SSL_SESSION_set_down_load(s->sessions, i);
CRYPTO_THREAD_unlock(s->lock);
sk_SSL_SESSION_pop_free(sk, SSL_SESSION_free);
}
int ssl_clear_bad_session(SSL *s)
{
if ((s->session != NULL) &&
!(s->shutdown & SSL_SENT_SHUTDOWN) &&
!(SSL_in_init(s) || SSL_in_before(s))) {
SSL_CTX_remove_session(s->session_ctx, s->session);
return 1;
} else
return 0;
}
/* locked by SSL_CTX in the calling function */
static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s)
{
if ((s->next == NULL) || (s->prev == NULL))
return;
if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) {
/* last element in list */
if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) {
/* only one element in list */
ctx->session_cache_head = NULL;
ctx->session_cache_tail = NULL;
} else {
ctx->session_cache_tail = s->prev;
s->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
}
} else {
if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) {
/* first element in list */
ctx->session_cache_head = s->next;
s->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
} else {
/* middle of list */
s->next->prev = s->prev;
s->prev->next = s->next;
}
}
s->prev = s->next = NULL;
s->owner = NULL;
}
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
{
SSL_SESSION *next;
if ((s->next != NULL) && (s->prev != NULL))
SSL_SESSION_list_remove(ctx, s);
if (ctx->session_cache_head == NULL) {
ctx->session_cache_head = s;
ctx->session_cache_tail = s;
s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
s->next = (SSL_SESSION *)&(ctx->session_cache_tail);
} else {
if (timeoutcmp(s, ctx->session_cache_head) >= 0) {
/*
* if we timeout after (or the same time as) the first
* session, put us first - usual case
*/
s->next = ctx->session_cache_head;
s->next->prev = s;
s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
ctx->session_cache_head = s;
} else if (timeoutcmp(s, ctx->session_cache_tail) < 0) {
/* if we timeout before the last session, put us last */
s->prev = ctx->session_cache_tail;
s->prev->next = s;
s->next = (SSL_SESSION *)&(ctx->session_cache_tail);
ctx->session_cache_tail = s;
} else {
/*
* we timeout somewhere in-between - if there is only
* one session in the cache it will be caught above
*/
next = ctx->session_cache_head->next;
while (next != (SSL_SESSION*)&(ctx->session_cache_tail)) {
if (timeoutcmp(s, next) >= 0) {
s->next = next;
s->prev = next->prev;
next->prev->next = s;
next->prev = s;
break;
}
next = next->next;
}
}
}
s->owner = ctx;
}
void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
int (*cb) (struct ssl_st *ssl, SSL_SESSION *sess))
{
ctx->new_session_cb = cb;
}
int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (SSL *ssl, SSL_SESSION *sess) {
return ctx->new_session_cb;
}
void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
void (*cb) (SSL_CTX *ctx, SSL_SESSION *sess))
{
ctx->remove_session_cb = cb;
}
void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (SSL_CTX *ctx,
SSL_SESSION *sess) {
return ctx->remove_session_cb;
}
void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
SSL_SESSION *(*cb) (struct ssl_st *ssl,
const unsigned char *data,
int len, int *copy))
{
ctx->get_session_cb = cb;
}
SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (SSL *ssl,
const unsigned char
*data, int len,
int *copy) {
return ctx->get_session_cb;
}
void SSL_CTX_set_info_callback(SSL_CTX *ctx,
void (*cb) (const SSL *ssl, int type, int val))
{
ctx->info_callback = cb;
}
void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type,
int val) {
return ctx->info_callback;
}
void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
int (*cb) (SSL *ssl, X509 **x509,
EVP_PKEY **pkey))
{
ctx->client_cert_cb = cb;
}
int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509,
EVP_PKEY **pkey) {
return ctx->client_cert_cb;
}
void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
int (*cb) (SSL *ssl,
unsigned char *cookie,
unsigned int *cookie_len))
{
ctx->app_gen_cookie_cb = cb;
}
void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
int (*cb) (SSL *ssl,
const unsigned char *cookie,
unsigned int cookie_len))
{
ctx->app_verify_cookie_cb = cb;
}
int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len)
{
OPENSSL_free(ss->ticket_appdata);
ss->ticket_appdata_len = 0;
if (data == NULL || len == 0) {
ss->ticket_appdata = NULL;
return 1;
}
ss->ticket_appdata = OPENSSL_memdup(data, len);
if (ss->ticket_appdata != NULL) {
ss->ticket_appdata_len = len;
return 1;
}
return 0;
}
int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len)
{
*data = ss->ticket_appdata;
*len = ss->ticket_appdata_len;
return 1;
}
void SSL_CTX_set_stateless_cookie_generate_cb(
SSL_CTX *ctx,
int (*cb) (SSL *ssl,
unsigned char *cookie,
size_t *cookie_len))
{
ctx->gen_stateless_cookie_cb = cb;
}
void SSL_CTX_set_stateless_cookie_verify_cb(
SSL_CTX *ctx,
int (*cb) (SSL *ssl,
const unsigned char *cookie,
size_t cookie_len))
{
ctx->verify_stateless_cookie_cb = cb;
}
IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 51c2283db915..e6f4bcc04533 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1,3508 +1,3509 @@
/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * 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 <stdlib.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/core_names.h>
#include <openssl/ocsp.h>
#include <openssl/conf.h>
#include <openssl/x509v3.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/provider.h>
#include <openssl/param_build.h>
#include "internal/nelem.h"
#include "internal/sizes.h"
#include "internal/tlsgroups.h"
#include "ssl_local.h"
#include <openssl/ct.h>
static const SIGALG_LOOKUP *find_sig_alg(SSL *s, X509 *x, EVP_PKEY *pkey);
static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu);
SSL3_ENC_METHOD const TLSv1_enc_data = {
tls1_enc,
tls1_mac,
tls1_setup_key_block,
tls1_generate_master_secret,
tls1_change_cipher_state,
tls1_final_finish_mac,
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
tls1_alert_code,
tls1_export_keying_material,
0,
ssl3_set_handshake_header,
tls_close_construct_packet,
ssl3_handshake_write
};
SSL3_ENC_METHOD const TLSv1_1_enc_data = {
tls1_enc,
tls1_mac,
tls1_setup_key_block,
tls1_generate_master_secret,
tls1_change_cipher_state,
tls1_final_finish_mac,
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
tls1_alert_code,
tls1_export_keying_material,
SSL_ENC_FLAG_EXPLICIT_IV,
ssl3_set_handshake_header,
tls_close_construct_packet,
ssl3_handshake_write
};
SSL3_ENC_METHOD const TLSv1_2_enc_data = {
tls1_enc,
tls1_mac,
tls1_setup_key_block,
tls1_generate_master_secret,
tls1_change_cipher_state,
tls1_final_finish_mac,
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
tls1_alert_code,
tls1_export_keying_material,
SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF
| SSL_ENC_FLAG_TLS1_2_CIPHERS,
ssl3_set_handshake_header,
tls_close_construct_packet,
ssl3_handshake_write
};
SSL3_ENC_METHOD const TLSv1_3_enc_data = {
tls13_enc,
tls1_mac,
tls13_setup_key_block,
tls13_generate_master_secret,
tls13_change_cipher_state,
tls13_final_finish_mac,
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
tls13_alert_code,
tls13_export_keying_material,
SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF,
ssl3_set_handshake_header,
tls_close_construct_packet,
ssl3_handshake_write
};
long tls1_default_timeout(void)
{
/*
* 2 hours, the 24 hours mentioned in the TLSv1 spec is way too long for
* http, the cache would over fill
*/
return (60 * 60 * 2);
}
int tls1_new(SSL *s)
{
if (!ssl3_new(s))
return 0;
if (!s->method->ssl_clear(s))
return 0;
return 1;
}
void tls1_free(SSL *s)
{
OPENSSL_free(s->ext.session_ticket);
ssl3_free(s);
}
int tls1_clear(SSL *s)
{
if (!ssl3_clear(s))
return 0;
if (s->method->version == TLS_ANY_VERSION)
s->version = TLS_MAX_VERSION_INTERNAL;
else
s->version = s->method->version;
return 1;
}
/* Legacy NID to group_id mapping. Only works for groups we know about */
static struct {
int nid;
uint16_t group_id;
} nid_to_group[] = {
{NID_sect163k1, OSSL_TLS_GROUP_ID_sect163k1},
{NID_sect163r1, OSSL_TLS_GROUP_ID_sect163r1},
{NID_sect163r2, OSSL_TLS_GROUP_ID_sect163r2},
{NID_sect193r1, OSSL_TLS_GROUP_ID_sect193r1},
{NID_sect193r2, OSSL_TLS_GROUP_ID_sect193r2},
{NID_sect233k1, OSSL_TLS_GROUP_ID_sect233k1},
{NID_sect233r1, OSSL_TLS_GROUP_ID_sect233r1},
{NID_sect239k1, OSSL_TLS_GROUP_ID_sect239k1},
{NID_sect283k1, OSSL_TLS_GROUP_ID_sect283k1},
{NID_sect283r1, OSSL_TLS_GROUP_ID_sect283r1},
{NID_sect409k1, OSSL_TLS_GROUP_ID_sect409k1},
{NID_sect409r1, OSSL_TLS_GROUP_ID_sect409r1},
{NID_sect571k1, OSSL_TLS_GROUP_ID_sect571k1},
{NID_sect571r1, OSSL_TLS_GROUP_ID_sect571r1},
{NID_secp160k1, OSSL_TLS_GROUP_ID_secp160k1},
{NID_secp160r1, OSSL_TLS_GROUP_ID_secp160r1},
{NID_secp160r2, OSSL_TLS_GROUP_ID_secp160r2},
{NID_secp192k1, OSSL_TLS_GROUP_ID_secp192k1},
{NID_X9_62_prime192v1, OSSL_TLS_GROUP_ID_secp192r1},
{NID_secp224k1, OSSL_TLS_GROUP_ID_secp224k1},
{NID_secp224r1, OSSL_TLS_GROUP_ID_secp224r1},
{NID_secp256k1, OSSL_TLS_GROUP_ID_secp256k1},
{NID_X9_62_prime256v1, OSSL_TLS_GROUP_ID_secp256r1},
{NID_secp384r1, OSSL_TLS_GROUP_ID_secp384r1},
{NID_secp521r1, OSSL_TLS_GROUP_ID_secp521r1},
{NID_brainpoolP256r1, OSSL_TLS_GROUP_ID_brainpoolP256r1},
{NID_brainpoolP384r1, OSSL_TLS_GROUP_ID_brainpoolP384r1},
{NID_brainpoolP512r1, OSSL_TLS_GROUP_ID_brainpoolP512r1},
{EVP_PKEY_X25519, OSSL_TLS_GROUP_ID_x25519},
{EVP_PKEY_X448, OSSL_TLS_GROUP_ID_x448},
{NID_id_tc26_gost_3410_2012_256_paramSetA, 0x0022},
{NID_id_tc26_gost_3410_2012_256_paramSetB, 0x0023},
{NID_id_tc26_gost_3410_2012_256_paramSetC, 0x0024},
{NID_id_tc26_gost_3410_2012_256_paramSetD, 0x0025},
{NID_id_tc26_gost_3410_2012_512_paramSetA, 0x0026},
{NID_id_tc26_gost_3410_2012_512_paramSetB, 0x0027},
{NID_id_tc26_gost_3410_2012_512_paramSetC, 0x0028},
{NID_ffdhe2048, OSSL_TLS_GROUP_ID_ffdhe2048},
{NID_ffdhe3072, OSSL_TLS_GROUP_ID_ffdhe3072},
{NID_ffdhe4096, OSSL_TLS_GROUP_ID_ffdhe4096},
{NID_ffdhe6144, OSSL_TLS_GROUP_ID_ffdhe6144},
{NID_ffdhe8192, OSSL_TLS_GROUP_ID_ffdhe8192}
};
static const unsigned char ecformats_default[] = {
TLSEXT_ECPOINTFORMAT_uncompressed,
TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime,
TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2
};
/* The default curves */
static const uint16_t supported_groups_default[] = {
29, /* X25519 (29) */
23, /* secp256r1 (23) */
30, /* X448 (30) */
25, /* secp521r1 (25) */
24, /* secp384r1 (24) */
34, /* GC256A (34) */
35, /* GC256B (35) */
36, /* GC256C (36) */
37, /* GC256D (37) */
38, /* GC512A (38) */
39, /* GC512B (39) */
40, /* GC512C (40) */
0x100, /* ffdhe2048 (0x100) */
0x101, /* ffdhe3072 (0x101) */
0x102, /* ffdhe4096 (0x102) */
0x103, /* ffdhe6144 (0x103) */
0x104, /* ffdhe8192 (0x104) */
};
static const uint16_t suiteb_curves[] = {
TLSEXT_curve_P_256,
TLSEXT_curve_P_384
};
struct provider_group_data_st {
SSL_CTX *ctx;
OSSL_PROVIDER *provider;
};
#define TLS_GROUP_LIST_MALLOC_BLOCK_SIZE 10
static OSSL_CALLBACK add_provider_groups;
static int add_provider_groups(const OSSL_PARAM params[], void *data)
{
struct provider_group_data_st *pgd = data;
SSL_CTX *ctx = pgd->ctx;
OSSL_PROVIDER *provider = pgd->provider;
const OSSL_PARAM *p;
TLS_GROUP_INFO *ginf = NULL;
EVP_KEYMGMT *keymgmt;
unsigned int gid;
unsigned int is_kem = 0;
int ret = 0;
if (ctx->group_list_max_len == ctx->group_list_len) {
TLS_GROUP_INFO *tmp = NULL;
if (ctx->group_list_max_len == 0)
tmp = OPENSSL_malloc(sizeof(TLS_GROUP_INFO)
* TLS_GROUP_LIST_MALLOC_BLOCK_SIZE);
else
tmp = OPENSSL_realloc(ctx->group_list,
(ctx->group_list_max_len
+ TLS_GROUP_LIST_MALLOC_BLOCK_SIZE)
* sizeof(TLS_GROUP_INFO));
if (tmp == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
ctx->group_list = tmp;
memset(tmp + ctx->group_list_max_len,
0,
sizeof(TLS_GROUP_INFO) * TLS_GROUP_LIST_MALLOC_BLOCK_SIZE);
ctx->group_list_max_len += TLS_GROUP_LIST_MALLOC_BLOCK_SIZE;
}
ginf = &ctx->group_list[ctx->group_list_len];
p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_NAME);
if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
ginf->tlsname = OPENSSL_strdup(p->data);
if (ginf->tlsname == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL);
if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
ginf->realname = OPENSSL_strdup(p->data);
if (ginf->realname == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_ID);
if (p == NULL || !OSSL_PARAM_get_uint(p, &gid) || gid > UINT16_MAX) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
ginf->group_id = (uint16_t)gid;
p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_ALG);
if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
ginf->algorithm = OPENSSL_strdup(p->data);
if (ginf->algorithm == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS);
if (p == NULL || !OSSL_PARAM_get_uint(p, &ginf->secbits)) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_IS_KEM);
if (p != NULL && (!OSSL_PARAM_get_uint(p, &is_kem) || is_kem > 1)) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
ginf->is_kem = 1 & is_kem;
p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_MIN_TLS);
if (p == NULL || !OSSL_PARAM_get_int(p, &ginf->mintls)) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_MAX_TLS);
if (p == NULL || !OSSL_PARAM_get_int(p, &ginf->maxtls)) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS);
if (p == NULL || !OSSL_PARAM_get_int(p, &ginf->mindtls)) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS);
if (p == NULL || !OSSL_PARAM_get_int(p, &ginf->maxdtls)) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
/*
* Now check that the algorithm is actually usable for our property query
* string. Regardless of the result we still return success because we have
* successfully processed this group, even though we may decide not to use
* it.
*/
ret = 1;
ERR_set_mark();
keymgmt = EVP_KEYMGMT_fetch(ctx->libctx, ginf->algorithm, ctx->propq);
if (keymgmt != NULL) {
/*
* We have successfully fetched the algorithm - however if the provider
* doesn't match this one then we ignore it.
*
* Note: We're cheating a little here. Technically if the same algorithm
* is available from more than one provider then it is undefined which
* implementation you will get back. Theoretically this could be
* different every time...we assume here that you'll always get the
* same one back if you repeat the exact same fetch. Is this a reasonable
* assumption to make (in which case perhaps we should document this
* behaviour)?
*/
if (EVP_KEYMGMT_get0_provider(keymgmt) == provider) {
/* We have a match - so we will use this group */
ctx->group_list_len++;
ginf = NULL;
}
EVP_KEYMGMT_free(keymgmt);
}
ERR_pop_to_mark();
err:
if (ginf != NULL) {
OPENSSL_free(ginf->tlsname);
OPENSSL_free(ginf->realname);
OPENSSL_free(ginf->algorithm);
ginf->algorithm = ginf->tlsname = ginf->realname = NULL;
}
return ret;
}
static int discover_provider_groups(OSSL_PROVIDER *provider, void *vctx)
{
struct provider_group_data_st pgd;
pgd.ctx = vctx;
pgd.provider = provider;
return OSSL_PROVIDER_get_capabilities(provider, "TLS-GROUP",
add_provider_groups, &pgd);
}
int ssl_load_groups(SSL_CTX *ctx)
{
size_t i, j, num_deflt_grps = 0;
uint16_t tmp_supp_groups[OSSL_NELEM(supported_groups_default)];
if (!OSSL_PROVIDER_do_all(ctx->libctx, discover_provider_groups, ctx))
return 0;
for (i = 0; i < OSSL_NELEM(supported_groups_default); i++) {
for (j = 0; j < ctx->group_list_len; j++) {
if (ctx->group_list[j].group_id == supported_groups_default[i]) {
tmp_supp_groups[num_deflt_grps++] = ctx->group_list[j].group_id;
break;
}
}
}
if (num_deflt_grps == 0)
return 1;
ctx->ext.supported_groups_default
= OPENSSL_malloc(sizeof(uint16_t) * num_deflt_grps);
if (ctx->ext.supported_groups_default == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(ctx->ext.supported_groups_default,
tmp_supp_groups,
num_deflt_grps * sizeof(tmp_supp_groups[0]));
ctx->ext.supported_groups_default_len = num_deflt_grps;
return 1;
}
static uint16_t tls1_group_name2id(SSL_CTX *ctx, const char *name)
{
size_t i;
for (i = 0; i < ctx->group_list_len; i++) {
if (strcmp(ctx->group_list[i].tlsname, name) == 0
|| strcmp(ctx->group_list[i].realname, name) == 0)
return ctx->group_list[i].group_id;
}
return 0;
}
const TLS_GROUP_INFO *tls1_group_id_lookup(SSL_CTX *ctx, uint16_t group_id)
{
size_t i;
for (i = 0; i < ctx->group_list_len; i++) {
if (ctx->group_list[i].group_id == group_id)
return &ctx->group_list[i];
}
return NULL;
}
int tls1_group_id2nid(uint16_t group_id, int include_unknown)
{
size_t i;
if (group_id == 0)
return NID_undef;
/*
* Return well known Group NIDs - for backwards compatibility. This won't
* work for groups we don't know about.
*/
for (i = 0; i < OSSL_NELEM(nid_to_group); i++)
{
if (nid_to_group[i].group_id == group_id)
return nid_to_group[i].nid;
}
if (!include_unknown)
return NID_undef;
return TLSEXT_nid_unknown | (int)group_id;
}
uint16_t tls1_nid2group_id(int nid)
{
size_t i;
/*
* Return well known Group ids - for backwards compatibility. This won't
* work for groups we don't know about.
*/
for (i = 0; i < OSSL_NELEM(nid_to_group); i++)
{
if (nid_to_group[i].nid == nid)
return nid_to_group[i].group_id;
}
return 0;
}
/*
* Set *pgroups to the supported groups list and *pgroupslen to
* the number of groups supported.
*/
void tls1_get_supported_groups(SSL *s, const uint16_t **pgroups,
size_t *pgroupslen)
{
/* For Suite B mode only include P-256, P-384 */
switch (tls1_suiteb(s)) {
case SSL_CERT_FLAG_SUITEB_128_LOS:
*pgroups = suiteb_curves;
*pgroupslen = OSSL_NELEM(suiteb_curves);
break;
case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
*pgroups = suiteb_curves;
*pgroupslen = 1;
break;
case SSL_CERT_FLAG_SUITEB_192_LOS:
*pgroups = suiteb_curves + 1;
*pgroupslen = 1;
break;
default:
if (s->ext.supportedgroups == NULL) {
*pgroups = s->ctx->ext.supported_groups_default;
*pgroupslen = s->ctx->ext.supported_groups_default_len;
} else {
*pgroups = s->ext.supportedgroups;
*pgroupslen = s->ext.supportedgroups_len;
}
break;
}
}
int tls_valid_group(SSL *s, uint16_t group_id, int minversion, int maxversion,
int isec, int *okfortls13)
{
const TLS_GROUP_INFO *ginfo = tls1_group_id_lookup(s->ctx, group_id);
int ret;
if (okfortls13 != NULL)
*okfortls13 = 0;
if (ginfo == NULL)
return 0;
if (SSL_IS_DTLS(s)) {
if (ginfo->mindtls < 0 || ginfo->maxdtls < 0)
return 0;
if (ginfo->maxdtls == 0)
ret = 1;
else
ret = DTLS_VERSION_LE(minversion, ginfo->maxdtls);
if (ginfo->mindtls > 0)
ret &= DTLS_VERSION_GE(maxversion, ginfo->mindtls);
} else {
if (ginfo->mintls < 0 || ginfo->maxtls < 0)
return 0;
if (ginfo->maxtls == 0)
ret = 1;
else
ret = (minversion <= ginfo->maxtls);
if (ginfo->mintls > 0)
ret &= (maxversion >= ginfo->mintls);
if (ret && okfortls13 != NULL && maxversion == TLS1_3_VERSION)
*okfortls13 = (ginfo->maxtls == 0)
|| (ginfo->maxtls >= TLS1_3_VERSION);
}
ret &= !isec
|| strcmp(ginfo->algorithm, "EC") == 0
|| strcmp(ginfo->algorithm, "X25519") == 0
|| strcmp(ginfo->algorithm, "X448") == 0;
return ret;
}
/* See if group is allowed by security callback */
int tls_group_allowed(SSL *s, uint16_t group, int op)
{
const TLS_GROUP_INFO *ginfo = tls1_group_id_lookup(s->ctx, group);
unsigned char gtmp[2];
if (ginfo == NULL)
return 0;
gtmp[0] = group >> 8;
gtmp[1] = group & 0xff;
return ssl_security(s, op, ginfo->secbits,
tls1_group_id2nid(ginfo->group_id, 0), (void *)gtmp);
}
/* Return 1 if "id" is in "list" */
static int tls1_in_list(uint16_t id, const uint16_t *list, size_t listlen)
{
size_t i;
for (i = 0; i < listlen; i++)
if (list[i] == id)
return 1;
return 0;
}
/*-
* For nmatch >= 0, return the id of the |nmatch|th shared group or 0
* if there is no match.
* For nmatch == -1, return number of matches
* For nmatch == -2, return the id of the group to use for
* a tmp key, or 0 if there is no match.
*/
uint16_t tls1_shared_group(SSL *s, int nmatch)
{
const uint16_t *pref, *supp;
size_t num_pref, num_supp, i;
int k;
/* Can't do anything on client side */
if (s->server == 0)
return 0;
if (nmatch == -2) {
if (tls1_suiteb(s)) {
/*
* For Suite B ciphersuite determines curve: we already know
* these are acceptable due to previous checks.
*/
unsigned long cid = s->s3.tmp.new_cipher->id;
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
return TLSEXT_curve_P_256;
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
return TLSEXT_curve_P_384;
/* Should never happen */
return 0;
}
/* If not Suite B just return first preference shared curve */
nmatch = 0;
}
/*
* If server preference set, our groups are the preference order
* otherwise peer decides.
*/
if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
tls1_get_supported_groups(s, &pref, &num_pref);
tls1_get_peer_groups(s, &supp, &num_supp);
} else {
tls1_get_peer_groups(s, &pref, &num_pref);
tls1_get_supported_groups(s, &supp, &num_supp);
}
for (k = 0, i = 0; i < num_pref; i++) {
uint16_t id = pref[i];
if (!tls1_in_list(id, supp, num_supp)
|| !tls_group_allowed(s, id, SSL_SECOP_CURVE_SHARED))
continue;
if (nmatch == k)
return id;
k++;
}
if (nmatch == -1)
return k;
/* Out of range (nmatch > k). */
return 0;
}
int tls1_set_groups(uint16_t **pext, size_t *pextlen,
int *groups, size_t ngroups)
{
uint16_t *glist;
size_t i;
/*
* Bitmap of groups included to detect duplicates: two variables are added
* to detect duplicates as some values are more than 32.
*/
unsigned long *dup_list = NULL;
unsigned long dup_list_egrp = 0;
unsigned long dup_list_dhgrp = 0;
if (ngroups == 0) {
ERR_raise(ERR_LIB_SSL, SSL_R_BAD_LENGTH);
return 0;
}
if ((glist = OPENSSL_malloc(ngroups * sizeof(*glist))) == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0; i < ngroups; i++) {
unsigned long idmask;
uint16_t id;
id = tls1_nid2group_id(groups[i]);
if ((id & 0x00FF) >= (sizeof(unsigned long) * 8))
goto err;
idmask = 1L << (id & 0x00FF);
dup_list = (id < 0x100) ? &dup_list_egrp : &dup_list_dhgrp;
if (!id || ((*dup_list) & idmask))
goto err;
*dup_list |= idmask;
glist[i] = id;
}
OPENSSL_free(*pext);
*pext = glist;
*pextlen = ngroups;
return 1;
err:
OPENSSL_free(glist);
return 0;
}
# define GROUPLIST_INCREMENT 40
# define GROUP_NAME_BUFFER_LENGTH 64
typedef struct {
SSL_CTX *ctx;
size_t gidcnt;
size_t gidmax;
uint16_t *gid_arr;
} gid_cb_st;
static int gid_cb(const char *elem, int len, void *arg)
{
gid_cb_st *garg = arg;
size_t i;
uint16_t gid = 0;
char etmp[GROUP_NAME_BUFFER_LENGTH];
if (elem == NULL)
return 0;
if (garg->gidcnt == garg->gidmax) {
uint16_t *tmp =
OPENSSL_realloc(garg->gid_arr, garg->gidmax + GROUPLIST_INCREMENT);
if (tmp == NULL)
return 0;
garg->gidmax += GROUPLIST_INCREMENT;
garg->gid_arr = tmp;
}
if (len > (int)(sizeof(etmp) - 1))
return 0;
memcpy(etmp, elem, len);
etmp[len] = 0;
gid = tls1_group_name2id(garg->ctx, etmp);
if (gid == 0) {
ERR_raise_data(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT,
"group '%s' cannot be set", etmp);
return 0;
}
for (i = 0; i < garg->gidcnt; i++)
if (garg->gid_arr[i] == gid)
return 0;
garg->gid_arr[garg->gidcnt++] = gid;
return 1;
}
/* Set groups based on a colon separated list */
int tls1_set_groups_list(SSL_CTX *ctx, uint16_t **pext, size_t *pextlen,
const char *str)
{
gid_cb_st gcb;
uint16_t *tmparr;
int ret = 0;
gcb.gidcnt = 0;
gcb.gidmax = GROUPLIST_INCREMENT;
gcb.gid_arr = OPENSSL_malloc(gcb.gidmax * sizeof(*gcb.gid_arr));
if (gcb.gid_arr == NULL)
return 0;
gcb.ctx = ctx;
if (!CONF_parse_list(str, ':', 1, gid_cb, &gcb))
goto end;
if (pext == NULL) {
ret = 1;
goto end;
}
/*
* gid_cb ensurse there are no duplicates so we can just go ahead and set
* the result
*/
tmparr = OPENSSL_memdup(gcb.gid_arr, gcb.gidcnt * sizeof(*tmparr));
if (tmparr == NULL)
goto end;
+ OPENSSL_free(*pext);
*pext = tmparr;
*pextlen = gcb.gidcnt;
ret = 1;
end:
OPENSSL_free(gcb.gid_arr);
return ret;
}
/* Check a group id matches preferences */
int tls1_check_group_id(SSL *s, uint16_t group_id, int check_own_groups)
{
const uint16_t *groups;
size_t groups_len;
if (group_id == 0)
return 0;
/* Check for Suite B compliance */
if (tls1_suiteb(s) && s->s3.tmp.new_cipher != NULL) {
unsigned long cid = s->s3.tmp.new_cipher->id;
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) {
if (group_id != TLSEXT_curve_P_256)
return 0;
} else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) {
if (group_id != TLSEXT_curve_P_384)
return 0;
} else {
/* Should never happen */
return 0;
}
}
if (check_own_groups) {
/* Check group is one of our preferences */
tls1_get_supported_groups(s, &groups, &groups_len);
if (!tls1_in_list(group_id, groups, groups_len))
return 0;
}
if (!tls_group_allowed(s, group_id, SSL_SECOP_CURVE_CHECK))
return 0;
/* For clients, nothing more to check */
if (!s->server)
return 1;
/* Check group is one of peers preferences */
tls1_get_peer_groups(s, &groups, &groups_len);
/*
* RFC 4492 does not require the supported elliptic curves extension
* so if it is not sent we can just choose any curve.
* It is invalid to send an empty list in the supported groups
* extension, so groups_len == 0 always means no extension.
*/
if (groups_len == 0)
return 1;
return tls1_in_list(group_id, groups, groups_len);
}
void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
size_t *num_formats)
{
/*
* If we have a custom point format list use it otherwise use default
*/
if (s->ext.ecpointformats) {
*pformats = s->ext.ecpointformats;
*num_formats = s->ext.ecpointformats_len;
} else {
*pformats = ecformats_default;
/* For Suite B we don't support char2 fields */
if (tls1_suiteb(s))
*num_formats = sizeof(ecformats_default) - 1;
else
*num_formats = sizeof(ecformats_default);
}
}
/* Check a key is compatible with compression extension */
static int tls1_check_pkey_comp(SSL *s, EVP_PKEY *pkey)
{
unsigned char comp_id;
size_t i;
int point_conv;
/* If not an EC key nothing to check */
if (!EVP_PKEY_is_a(pkey, "EC"))
return 1;
/* Get required compression id */
point_conv = EVP_PKEY_get_ec_point_conv_form(pkey);
if (point_conv == 0)
return 0;
if (point_conv == POINT_CONVERSION_UNCOMPRESSED) {
comp_id = TLSEXT_ECPOINTFORMAT_uncompressed;
} else if (SSL_IS_TLS13(s)) {
/*
* ec_point_formats extension is not used in TLSv1.3 so we ignore
* this check.
*/
return 1;
} else {
int field_type = EVP_PKEY_get_field_type(pkey);
if (field_type == NID_X9_62_prime_field)
comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
else if (field_type == NID_X9_62_characteristic_two_field)
comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
else
return 0;
}
/*
* If point formats extension present check it, otherwise everything is
* supported (see RFC4492).
*/
if (s->ext.peer_ecpointformats == NULL)
return 1;
for (i = 0; i < s->ext.peer_ecpointformats_len; i++) {
if (s->ext.peer_ecpointformats[i] == comp_id)
return 1;
}
return 0;
}
/* Return group id of a key */
static uint16_t tls1_get_group_id(EVP_PKEY *pkey)
{
int curve_nid = ssl_get_EC_curve_nid(pkey);
if (curve_nid == NID_undef)
return 0;
return tls1_nid2group_id(curve_nid);
}
/*
* Check cert parameters compatible with extensions: currently just checks EC
* certificates have compatible curves and compression.
*/
static int tls1_check_cert_param(SSL *s, X509 *x, int check_ee_md)
{
uint16_t group_id;
EVP_PKEY *pkey;
pkey = X509_get0_pubkey(x);
if (pkey == NULL)
return 0;
/* If not EC nothing to do */
if (!EVP_PKEY_is_a(pkey, "EC"))
return 1;
/* Check compression */
if (!tls1_check_pkey_comp(s, pkey))
return 0;
group_id = tls1_get_group_id(pkey);
/*
* For a server we allow the certificate to not be in our list of supported
* groups.
*/
if (!tls1_check_group_id(s, group_id, !s->server))
return 0;
/*
* Special case for suite B. We *MUST* sign using SHA256+P-256 or
* SHA384+P-384.
*/
if (check_ee_md && tls1_suiteb(s)) {
int check_md;
size_t i;
/* Check to see we have necessary signing algorithm */
if (group_id == TLSEXT_curve_P_256)
check_md = NID_ecdsa_with_SHA256;
else if (group_id == TLSEXT_curve_P_384)
check_md = NID_ecdsa_with_SHA384;
else
return 0; /* Should never happen */
for (i = 0; i < s->shared_sigalgslen; i++) {
if (check_md == s->shared_sigalgs[i]->sigandhash)
return 1;;
}
return 0;
}
return 1;
}
/*
* tls1_check_ec_tmp_key - Check EC temporary key compatibility
* @s: SSL connection
* @cid: Cipher ID we're considering using
*
* Checks that the kECDHE cipher suite we're considering using
* is compatible with the client extensions.
*
* Returns 0 when the cipher can't be used or 1 when it can.
*/
int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
{
/* If not Suite B just need a shared group */
if (!tls1_suiteb(s))
return tls1_shared_group(s, 0) != 0;
/*
* If Suite B, AES128 MUST use P-256 and AES256 MUST use P-384, no other
* curves permitted.
*/
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
return tls1_check_group_id(s, TLSEXT_curve_P_256, 1);
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
return tls1_check_group_id(s, TLSEXT_curve_P_384, 1);
return 0;
}
/* Default sigalg schemes */
static const uint16_t tls12_sigalgs[] = {
TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
TLSEXT_SIGALG_ed25519,
TLSEXT_SIGALG_ed448,
TLSEXT_SIGALG_rsa_pss_pss_sha256,
TLSEXT_SIGALG_rsa_pss_pss_sha384,
TLSEXT_SIGALG_rsa_pss_pss_sha512,
TLSEXT_SIGALG_rsa_pss_rsae_sha256,
TLSEXT_SIGALG_rsa_pss_rsae_sha384,
TLSEXT_SIGALG_rsa_pss_rsae_sha512,
TLSEXT_SIGALG_rsa_pkcs1_sha256,
TLSEXT_SIGALG_rsa_pkcs1_sha384,
TLSEXT_SIGALG_rsa_pkcs1_sha512,
TLSEXT_SIGALG_ecdsa_sha224,
TLSEXT_SIGALG_ecdsa_sha1,
TLSEXT_SIGALG_rsa_pkcs1_sha224,
TLSEXT_SIGALG_rsa_pkcs1_sha1,
TLSEXT_SIGALG_dsa_sha224,
TLSEXT_SIGALG_dsa_sha1,
TLSEXT_SIGALG_dsa_sha256,
TLSEXT_SIGALG_dsa_sha384,
TLSEXT_SIGALG_dsa_sha512,
#ifndef OPENSSL_NO_GOST
TLSEXT_SIGALG_gostr34102012_256_intrinsic,
TLSEXT_SIGALG_gostr34102012_512_intrinsic,
TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256,
TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512,
TLSEXT_SIGALG_gostr34102001_gostr3411,
#endif
};
static const uint16_t suiteb_sigalgs[] = {
TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
TLSEXT_SIGALG_ecdsa_secp384r1_sha384
};
static const SIGALG_LOOKUP sigalg_lookup_tbl[] = {
{"ecdsa_secp256r1_sha256", TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
NID_ecdsa_with_SHA256, NID_X9_62_prime256v1, 1},
{"ecdsa_secp384r1_sha384", TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
NID_ecdsa_with_SHA384, NID_secp384r1, 1},
{"ecdsa_secp521r1_sha512", TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
NID_ecdsa_with_SHA512, NID_secp521r1, 1},
{"ed25519", TLSEXT_SIGALG_ed25519,
NID_undef, -1, EVP_PKEY_ED25519, SSL_PKEY_ED25519,
NID_undef, NID_undef, 1},
{"ed448", TLSEXT_SIGALG_ed448,
NID_undef, -1, EVP_PKEY_ED448, SSL_PKEY_ED448,
NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_ecdsa_sha224,
NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
NID_ecdsa_with_SHA224, NID_undef, 1},
{NULL, TLSEXT_SIGALG_ecdsa_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
NID_ecdsa_with_SHA1, NID_undef, 1},
{"rsa_pss_rsae_sha256", TLSEXT_SIGALG_rsa_pss_rsae_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
NID_undef, NID_undef, 1},
{"rsa_pss_rsae_sha384", TLSEXT_SIGALG_rsa_pss_rsae_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
NID_undef, NID_undef, 1},
{"rsa_pss_rsae_sha512", TLSEXT_SIGALG_rsa_pss_rsae_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
NID_undef, NID_undef, 1},
{"rsa_pss_pss_sha256", TLSEXT_SIGALG_rsa_pss_pss_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
NID_undef, NID_undef, 1},
{"rsa_pss_pss_sha384", TLSEXT_SIGALG_rsa_pss_pss_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
NID_undef, NID_undef, 1},
{"rsa_pss_pss_sha512", TLSEXT_SIGALG_rsa_pss_pss_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
NID_undef, NID_undef, 1},
{"rsa_pkcs1_sha256", TLSEXT_SIGALG_rsa_pkcs1_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha256WithRSAEncryption, NID_undef, 1},
{"rsa_pkcs1_sha384", TLSEXT_SIGALG_rsa_pkcs1_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha384WithRSAEncryption, NID_undef, 1},
{"rsa_pkcs1_sha512", TLSEXT_SIGALG_rsa_pkcs1_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha512WithRSAEncryption, NID_undef, 1},
{"rsa_pkcs1_sha224", TLSEXT_SIGALG_rsa_pkcs1_sha224,
NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha224WithRSAEncryption, NID_undef, 1},
{"rsa_pkcs1_sha1", TLSEXT_SIGALG_rsa_pkcs1_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_sha1WithRSAEncryption, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha256,
NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
NID_dsa_with_SHA256, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha384,
NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha512,
NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha224,
NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_dsa_sha1,
NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
NID_dsaWithSHA1, NID_undef, 1},
#ifndef OPENSSL_NO_GOST
{NULL, TLSEXT_SIGALG_gostr34102012_256_intrinsic,
NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX,
NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256,
NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_gostr34102012_512_intrinsic,
NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX,
NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512,
NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256,
NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX,
NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256,
NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512,
NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX,
NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512,
NID_undef, NID_undef, 1},
{NULL, TLSEXT_SIGALG_gostr34102001_gostr3411,
NID_id_GostR3411_94, SSL_MD_GOST94_IDX,
NID_id_GostR3410_2001, SSL_PKEY_GOST01,
NID_undef, NID_undef, 1}
#endif
};
/* Legacy sigalgs for TLS < 1.2 RSA TLS signatures */
static const SIGALG_LOOKUP legacy_rsa_sigalg = {
"rsa_pkcs1_md5_sha1", 0,
NID_md5_sha1, SSL_MD_MD5_SHA1_IDX,
EVP_PKEY_RSA, SSL_PKEY_RSA,
NID_undef, NID_undef, 1
};
/*
* Default signature algorithm values used if signature algorithms not present.
* From RFC5246. Note: order must match certificate index order.
*/
static const uint16_t tls_default_sigalg[] = {
TLSEXT_SIGALG_rsa_pkcs1_sha1, /* SSL_PKEY_RSA */
0, /* SSL_PKEY_RSA_PSS_SIGN */
TLSEXT_SIGALG_dsa_sha1, /* SSL_PKEY_DSA_SIGN */
TLSEXT_SIGALG_ecdsa_sha1, /* SSL_PKEY_ECC */
TLSEXT_SIGALG_gostr34102001_gostr3411, /* SSL_PKEY_GOST01 */
TLSEXT_SIGALG_gostr34102012_256_intrinsic, /* SSL_PKEY_GOST12_256 */
TLSEXT_SIGALG_gostr34102012_512_intrinsic, /* SSL_PKEY_GOST12_512 */
0, /* SSL_PKEY_ED25519 */
0, /* SSL_PKEY_ED448 */
};
int ssl_setup_sig_algs(SSL_CTX *ctx)
{
size_t i;
const SIGALG_LOOKUP *lu;
SIGALG_LOOKUP *cache
= OPENSSL_malloc(sizeof(*lu) * OSSL_NELEM(sigalg_lookup_tbl));
EVP_PKEY *tmpkey = EVP_PKEY_new();
int ret = 0;
if (cache == NULL || tmpkey == NULL)
goto err;
ERR_set_mark();
for (i = 0, lu = sigalg_lookup_tbl;
i < OSSL_NELEM(sigalg_lookup_tbl); lu++, i++) {
EVP_PKEY_CTX *pctx;
cache[i] = *lu;
/*
* Check hash is available.
* This test is not perfect. A provider could have support
* for a signature scheme, but not a particular hash. However the hash
* could be available from some other loaded provider. In that case it
* could be that the signature is available, and the hash is available
* independently - but not as a combination. We ignore this for now.
*/
if (lu->hash != NID_undef
&& ctx->ssl_digest_methods[lu->hash_idx] == NULL) {
cache[i].enabled = 0;
continue;
}
if (!EVP_PKEY_set_type(tmpkey, lu->sig)) {
cache[i].enabled = 0;
continue;
}
pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, tmpkey, ctx->propq);
/* If unable to create pctx we assume the sig algorithm is unavailable */
if (pctx == NULL)
cache[i].enabled = 0;
EVP_PKEY_CTX_free(pctx);
}
ERR_pop_to_mark();
ctx->sigalg_lookup_cache = cache;
cache = NULL;
ret = 1;
err:
OPENSSL_free(cache);
EVP_PKEY_free(tmpkey);
return ret;
}
/* Lookup TLS signature algorithm */
static const SIGALG_LOOKUP *tls1_lookup_sigalg(const SSL *s, uint16_t sigalg)
{
size_t i;
const SIGALG_LOOKUP *lu;
for (i = 0, lu = s->ctx->sigalg_lookup_cache;
/* cache should have the same number of elements as sigalg_lookup_tbl */
i < OSSL_NELEM(sigalg_lookup_tbl);
lu++, i++) {
if (lu->sigalg == sigalg) {
if (!lu->enabled)
return NULL;
return lu;
}
}
return NULL;
}
/* Lookup hash: return 0 if invalid or not enabled */
int tls1_lookup_md(SSL_CTX *ctx, const SIGALG_LOOKUP *lu, const EVP_MD **pmd)
{
const EVP_MD *md;
if (lu == NULL)
return 0;
/* lu->hash == NID_undef means no associated digest */
if (lu->hash == NID_undef) {
md = NULL;
} else {
md = ssl_md(ctx, lu->hash_idx);
if (md == NULL)
return 0;
}
if (pmd)
*pmd = md;
return 1;
}
/*
* Check if key is large enough to generate RSA-PSS signature.
*
* The key must greater than or equal to 2 * hash length + 2.
* SHA512 has a hash length of 64 bytes, which is incompatible
* with a 128 byte (1024 bit) key.
*/
#define RSA_PSS_MINIMUM_KEY_SIZE(md) (2 * EVP_MD_get_size(md) + 2)
static int rsa_pss_check_min_key_size(SSL_CTX *ctx, const EVP_PKEY *pkey,
const SIGALG_LOOKUP *lu)
{
const EVP_MD *md;
if (pkey == NULL)
return 0;
if (!tls1_lookup_md(ctx, lu, &md) || md == NULL)
return 0;
if (EVP_PKEY_get_size(pkey) < RSA_PSS_MINIMUM_KEY_SIZE(md))
return 0;
return 1;
}
/*
* Returns a signature algorithm when the peer did not send a list of supported
* signature algorithms. The signature algorithm is fixed for the certificate
* type. |idx| is a certificate type index (SSL_PKEY_*). When |idx| is -1 the
* certificate type from |s| will be used.
* Returns the signature algorithm to use, or NULL on error.
*/
static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
{
if (idx == -1) {
if (s->server) {
size_t i;
/* Work out index corresponding to ciphersuite */
for (i = 0; i < SSL_PKEY_NUM; i++) {
const SSL_CERT_LOOKUP *clu = ssl_cert_lookup_by_idx(i);
if (clu == NULL)
continue;
if (clu->amask & s->s3.tmp.new_cipher->algorithm_auth) {
idx = i;
break;
}
}
/*
* Some GOST ciphersuites allow more than one signature algorithms
* */
if (idx == SSL_PKEY_GOST01 && s->s3.tmp.new_cipher->algorithm_auth != SSL_aGOST01) {
int real_idx;
for (real_idx = SSL_PKEY_GOST12_512; real_idx >= SSL_PKEY_GOST01;
real_idx--) {
if (s->cert->pkeys[real_idx].privatekey != NULL) {
idx = real_idx;
break;
}
}
}
/*
* As both SSL_PKEY_GOST12_512 and SSL_PKEY_GOST12_256 indices can be used
* with new (aGOST12-only) ciphersuites, we should find out which one is available really.
*/
else if (idx == SSL_PKEY_GOST12_256) {
int real_idx;
for (real_idx = SSL_PKEY_GOST12_512; real_idx >= SSL_PKEY_GOST12_256;
real_idx--) {
if (s->cert->pkeys[real_idx].privatekey != NULL) {
idx = real_idx;
break;
}
}
}
} else {
idx = s->cert->key - s->cert->pkeys;
}
}
if (idx < 0 || idx >= (int)OSSL_NELEM(tls_default_sigalg))
return NULL;
if (SSL_USE_SIGALGS(s) || idx != SSL_PKEY_RSA) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, tls_default_sigalg[idx]);
if (lu == NULL)
return NULL;
if (!tls1_lookup_md(s->ctx, lu, NULL))
return NULL;
if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
return NULL;
return lu;
}
if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, &legacy_rsa_sigalg))
return NULL;
return &legacy_rsa_sigalg;
}
/* Set peer sigalg based key type */
int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey)
{
size_t idx;
const SIGALG_LOOKUP *lu;
if (ssl_cert_lookup_by_pkey(pkey, &idx) == NULL)
return 0;
lu = tls1_get_legacy_sigalg(s, idx);
if (lu == NULL)
return 0;
s->s3.tmp.peer_sigalg = lu;
return 1;
}
size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs)
{
/*
* If Suite B mode use Suite B sigalgs only, ignore any other
* preferences.
*/
switch (tls1_suiteb(s)) {
case SSL_CERT_FLAG_SUITEB_128_LOS:
*psigs = suiteb_sigalgs;
return OSSL_NELEM(suiteb_sigalgs);
case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
*psigs = suiteb_sigalgs;
return 1;
case SSL_CERT_FLAG_SUITEB_192_LOS:
*psigs = suiteb_sigalgs + 1;
return 1;
}
/*
* We use client_sigalgs (if not NULL) if we're a server
* and sending a certificate request or if we're a client and
* determining which shared algorithm to use.
*/
if ((s->server == sent) && s->cert->client_sigalgs != NULL) {
*psigs = s->cert->client_sigalgs;
return s->cert->client_sigalgslen;
} else if (s->cert->conf_sigalgs) {
*psigs = s->cert->conf_sigalgs;
return s->cert->conf_sigalgslen;
} else {
*psigs = tls12_sigalgs;
return OSSL_NELEM(tls12_sigalgs);
}
}
/*
* Called by servers only. Checks that we have a sig alg that supports the
* specified EC curve.
*/
int tls_check_sigalg_curve(const SSL *s, int curve)
{
const uint16_t *sigs;
size_t siglen, i;
if (s->cert->conf_sigalgs) {
sigs = s->cert->conf_sigalgs;
siglen = s->cert->conf_sigalgslen;
} else {
sigs = tls12_sigalgs;
siglen = OSSL_NELEM(tls12_sigalgs);
}
for (i = 0; i < siglen; i++) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, sigs[i]);
if (lu == NULL)
continue;
if (lu->sig == EVP_PKEY_EC
&& lu->curve != NID_undef
&& curve == lu->curve)
return 1;
}
return 0;
}
/*
* Return the number of security bits for the signature algorithm, or 0 on
* error.
*/
static int sigalg_security_bits(SSL_CTX *ctx, const SIGALG_LOOKUP *lu)
{
const EVP_MD *md = NULL;
int secbits = 0;
if (!tls1_lookup_md(ctx, lu, &md))
return 0;
if (md != NULL)
{
int md_type = EVP_MD_get_type(md);
/* Security bits: half digest bits */
secbits = EVP_MD_get_size(md) * 4;
/*
* SHA1 and MD5 are known to be broken. Reduce security bits so that
* they're no longer accepted at security level 1. The real values don't
* really matter as long as they're lower than 80, which is our
* security level 1.
* https://eprint.iacr.org/2020/014 puts a chosen-prefix attack for
* SHA1 at 2^63.4 and MD5+SHA1 at 2^67.2
* https://documents.epfl.ch/users/l/le/lenstra/public/papers/lat.pdf
* puts a chosen-prefix attack for MD5 at 2^39.
*/
if (md_type == NID_sha1)
secbits = 64;
else if (md_type == NID_md5_sha1)
secbits = 67;
else if (md_type == NID_md5)
secbits = 39;
} else {
/* Values from https://tools.ietf.org/html/rfc8032#section-8.5 */
if (lu->sigalg == TLSEXT_SIGALG_ed25519)
secbits = 128;
else if (lu->sigalg == TLSEXT_SIGALG_ed448)
secbits = 224;
}
return secbits;
}
/*
* Check signature algorithm is consistent with sent supported signature
* algorithms and if so set relevant digest and signature scheme in
* s.
*/
int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
{
const uint16_t *sent_sigs;
const EVP_MD *md = NULL;
char sigalgstr[2];
size_t sent_sigslen, i, cidx;
int pkeyid = -1;
const SIGALG_LOOKUP *lu;
int secbits = 0;
pkeyid = EVP_PKEY_get_id(pkey);
/* Should never happen */
if (pkeyid == -1)
return -1;
if (SSL_IS_TLS13(s)) {
/* Disallow DSA for TLS 1.3 */
if (pkeyid == EVP_PKEY_DSA) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
/* Only allow PSS for TLS 1.3 */
if (pkeyid == EVP_PKEY_RSA)
pkeyid = EVP_PKEY_RSA_PSS;
}
lu = tls1_lookup_sigalg(s, sig);
/*
* Check sigalgs is known. Disallow SHA1/SHA224 with TLS 1.3. Check key type
* is consistent with signature: RSA keys can be used for RSA-PSS
*/
if (lu == NULL
|| (SSL_IS_TLS13(s) && (lu->hash == NID_sha1 || lu->hash == NID_sha224))
|| (pkeyid != lu->sig
&& (lu->sig != EVP_PKEY_RSA_PSS || pkeyid != EVP_PKEY_RSA))) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
/* Check the sigalg is consistent with the key OID */
if (!ssl_cert_lookup_by_nid(EVP_PKEY_get_id(pkey), &cidx)
|| lu->sig_idx != (int)cidx) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
if (pkeyid == EVP_PKEY_EC) {
/* Check point compression is permitted */
if (!tls1_check_pkey_comp(s, pkey)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_ILLEGAL_POINT_COMPRESSION);
return 0;
}
/* For TLS 1.3 or Suite B check curve matches signature algorithm */
if (SSL_IS_TLS13(s) || tls1_suiteb(s)) {
int curve = ssl_get_EC_curve_nid(pkey);
if (lu->curve != NID_undef && curve != lu->curve) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_CURVE);
return 0;
}
}
if (!SSL_IS_TLS13(s)) {
/* Check curve matches extensions */
if (!tls1_check_group_id(s, tls1_get_group_id(pkey), 1)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_CURVE);
return 0;
}
if (tls1_suiteb(s)) {
/* Check sigalg matches a permissible Suite B value */
if (sig != TLSEXT_SIGALG_ecdsa_secp256r1_sha256
&& sig != TLSEXT_SIGALG_ecdsa_secp384r1_sha384) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
}
}
} else if (tls1_suiteb(s)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
/* Check signature matches a type we sent */
sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
for (i = 0; i < sent_sigslen; i++, sent_sigs++) {
if (sig == *sent_sigs)
break;
}
/* Allow fallback to SHA1 if not strict mode */
if (i == sent_sigslen && (lu->hash != NID_sha1
|| s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
if (!tls1_lookup_md(s->ctx, lu, &md)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_UNKNOWN_DIGEST);
return 0;
}
/*
* Make sure security callback allows algorithm. For historical
* reasons we have to pass the sigalg as a two byte char array.
*/
sigalgstr[0] = (sig >> 8) & 0xff;
sigalgstr[1] = sig & 0xff;
secbits = sigalg_security_bits(s->ctx, lu);
if (secbits == 0 ||
!ssl_security(s, SSL_SECOP_SIGALG_CHECK, secbits,
md != NULL ? EVP_MD_get_type(md) : NID_undef,
(void *)sigalgstr)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
/* Store the sigalg the peer uses */
s->s3.tmp.peer_sigalg = lu;
return 1;
}
int SSL_get_peer_signature_type_nid(const SSL *s, int *pnid)
{
if (s->s3.tmp.peer_sigalg == NULL)
return 0;
*pnid = s->s3.tmp.peer_sigalg->sig;
return 1;
}
int SSL_get_signature_type_nid(const SSL *s, int *pnid)
{
if (s->s3.tmp.sigalg == NULL)
return 0;
*pnid = s->s3.tmp.sigalg->sig;
return 1;
}
/*
* Set a mask of disabled algorithms: an algorithm is disabled if it isn't
* supported, doesn't appear in supported signature algorithms, isn't supported
* by the enabled protocol versions or by the security level.
*
* This function should only be used for checking which ciphers are supported
* by the client.
*
* Call ssl_cipher_disabled() to check that it's enabled or not.
*/
int ssl_set_client_disabled(SSL *s)
{
s->s3.tmp.mask_a = 0;
s->s3.tmp.mask_k = 0;
ssl_set_sig_mask(&s->s3.tmp.mask_a, s, SSL_SECOP_SIGALG_MASK);
if (ssl_get_min_max_version(s, &s->s3.tmp.min_ver,
&s->s3.tmp.max_ver, NULL) != 0)
return 0;
#ifndef OPENSSL_NO_PSK
/* with PSK there must be client callback set */
if (!s->psk_client_callback) {
s->s3.tmp.mask_a |= SSL_aPSK;
s->s3.tmp.mask_k |= SSL_PSK;
}
#endif /* OPENSSL_NO_PSK */
#ifndef OPENSSL_NO_SRP
if (!(s->srp_ctx.srp_Mask & SSL_kSRP)) {
s->s3.tmp.mask_a |= SSL_aSRP;
s->s3.tmp.mask_k |= SSL_kSRP;
}
#endif
return 1;
}
/*
* ssl_cipher_disabled - check that a cipher is disabled or not
* @s: SSL connection that you want to use the cipher on
* @c: cipher to check
* @op: Security check that you want to do
* @ecdhe: If set to 1 then TLSv1 ECDHE ciphers are also allowed in SSLv3
*
* Returns 1 when it's disabled, 0 when enabled.
*/
int ssl_cipher_disabled(const SSL *s, const SSL_CIPHER *c, int op, int ecdhe)
{
if (c->algorithm_mkey & s->s3.tmp.mask_k
|| c->algorithm_auth & s->s3.tmp.mask_a)
return 1;
if (s->s3.tmp.max_ver == 0)
return 1;
if (!SSL_IS_DTLS(s)) {
int min_tls = c->min_tls;
/*
* For historical reasons we will allow ECHDE to be selected by a server
* in SSLv3 if we are a client
*/
if (min_tls == TLS1_VERSION && ecdhe
&& (c->algorithm_mkey & (SSL_kECDHE | SSL_kECDHEPSK)) != 0)
min_tls = SSL3_VERSION;
if ((min_tls > s->s3.tmp.max_ver) || (c->max_tls < s->s3.tmp.min_ver))
return 1;
}
if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3.tmp.max_ver)
|| DTLS_VERSION_LT(c->max_dtls, s->s3.tmp.min_ver)))
return 1;
return !ssl_security(s, op, c->strength_bits, 0, (void *)c);
}
int tls_use_ticket(SSL *s)
{
if ((s->options & SSL_OP_NO_TICKET))
return 0;
return ssl_security(s, SSL_SECOP_TICKET, 0, 0, NULL);
}
int tls1_set_server_sigalgs(SSL *s)
{
size_t i;
/* Clear any shared signature algorithms */
OPENSSL_free(s->shared_sigalgs);
s->shared_sigalgs = NULL;
s->shared_sigalgslen = 0;
/* Clear certificate validity flags */
for (i = 0; i < SSL_PKEY_NUM; i++)
s->s3.tmp.valid_flags[i] = 0;
/*
* If peer sent no signature algorithms check to see if we support
* the default algorithm for each certificate type
*/
if (s->s3.tmp.peer_cert_sigalgs == NULL
&& s->s3.tmp.peer_sigalgs == NULL) {
const uint16_t *sent_sigs;
size_t sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
for (i = 0; i < SSL_PKEY_NUM; i++) {
const SIGALG_LOOKUP *lu = tls1_get_legacy_sigalg(s, i);
size_t j;
if (lu == NULL)
continue;
/* Check default matches a type we sent */
for (j = 0; j < sent_sigslen; j++) {
if (lu->sigalg == sent_sigs[j]) {
s->s3.tmp.valid_flags[i] = CERT_PKEY_SIGN;
break;
}
}
}
return 1;
}
if (!tls1_process_sigalgs(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (s->shared_sigalgs != NULL)
return 1;
/* Fatal error if no shared signature algorithms */
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS);
return 0;
}
/*-
* Gets the ticket information supplied by the client if any.
*
* hello: The parsed ClientHello data
* ret: (output) on return, if a ticket was decrypted, then this is set to
* point to the resulting session.
*/
SSL_TICKET_STATUS tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
SSL_SESSION **ret)
{
size_t size;
RAW_EXTENSION *ticketext;
*ret = NULL;
s->ext.ticket_expected = 0;
/*
* If tickets disabled or not supported by the protocol version
* (e.g. TLSv1.3) behave as if no ticket present to permit stateful
* resumption.
*/
if (s->version <= SSL3_VERSION || !tls_use_ticket(s))
return SSL_TICKET_NONE;
ticketext = &hello->pre_proc_exts[TLSEXT_IDX_session_ticket];
if (!ticketext->present)
return SSL_TICKET_NONE;
size = PACKET_remaining(&ticketext->data);
return tls_decrypt_ticket(s, PACKET_data(&ticketext->data), size,
hello->session_id, hello->session_id_len, ret);
}
/*-
* tls_decrypt_ticket attempts to decrypt a session ticket.
*
* If s->tls_session_secret_cb is set and we're not doing TLSv1.3 then we are
* expecting a pre-shared key ciphersuite, in which case we have no use for
* session tickets and one will never be decrypted, nor will
* s->ext.ticket_expected be set to 1.
*
* Side effects:
* Sets s->ext.ticket_expected to 1 if the server will have to issue
* a new session ticket to the client because the client indicated support
* (and s->tls_session_secret_cb is NULL) but the client either doesn't have
* a session ticket or we couldn't use the one it gave us, or if
* s->ctx->ext.ticket_key_cb asked to renew the client's ticket.
* Otherwise, s->ext.ticket_expected is set to 0.
*
* etick: points to the body of the session ticket extension.
* eticklen: the length of the session tickets extension.
* sess_id: points at the session ID.
* sesslen: the length of the session ID.
* psess: (output) on return, if a ticket was decrypted, then this is set to
* point to the resulting session.
*/
SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick,
size_t eticklen, const unsigned char *sess_id,
size_t sesslen, SSL_SESSION **psess)
{
SSL_SESSION *sess = NULL;
unsigned char *sdec;
const unsigned char *p;
int slen, ivlen, renew_ticket = 0, declen;
SSL_TICKET_STATUS ret = SSL_TICKET_FATAL_ERR_OTHER;
size_t mlen;
unsigned char tick_hmac[EVP_MAX_MD_SIZE];
SSL_HMAC *hctx = NULL;
EVP_CIPHER_CTX *ctx = NULL;
SSL_CTX *tctx = s->session_ctx;
if (eticklen == 0) {
/*
* The client will accept a ticket but doesn't currently have
* one (TLSv1.2 and below), or treated as a fatal error in TLSv1.3
*/
ret = SSL_TICKET_EMPTY;
goto end;
}
if (!SSL_IS_TLS13(s) && s->ext.session_secret_cb) {
/*
* Indicate that the ticket couldn't be decrypted rather than
* generating the session from ticket now, trigger
* abbreviated handshake based on external mechanism to
* calculate the master secret later.
*/
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
/* Need at least keyname + iv */
if (eticklen < TLSEXT_KEYNAME_LENGTH + EVP_MAX_IV_LENGTH) {
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
/* Initialize session ticket encryption and HMAC contexts */
hctx = ssl_hmac_new(tctx);
if (hctx == NULL) {
ret = SSL_TICKET_FATAL_ERR_MALLOC;
goto end;
}
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) {
ret = SSL_TICKET_FATAL_ERR_MALLOC;
goto end;
}
#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
{
unsigned char *nctick = (unsigned char *)etick;
int rv = 0;
if (tctx->ext.ticket_key_evp_cb != NULL)
rv = tctx->ext.ticket_key_evp_cb(s, nctick,
nctick + TLSEXT_KEYNAME_LENGTH,
ctx,
ssl_hmac_get0_EVP_MAC_CTX(hctx),
0);
#ifndef OPENSSL_NO_DEPRECATED_3_0
else if (tctx->ext.ticket_key_cb != NULL)
/* if 0 is returned, write an empty ticket */
rv = tctx->ext.ticket_key_cb(s, nctick,
nctick + TLSEXT_KEYNAME_LENGTH,
ctx, ssl_hmac_get0_HMAC_CTX(hctx), 0);
#endif
if (rv < 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
if (rv == 0) {
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
if (rv == 2)
renew_ticket = 1;
} else {
EVP_CIPHER *aes256cbc = NULL;
/* Check key name matches */
if (memcmp(etick, tctx->ext.tick_key_name,
TLSEXT_KEYNAME_LENGTH) != 0) {
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
aes256cbc = EVP_CIPHER_fetch(s->ctx->libctx, "AES-256-CBC",
s->ctx->propq);
if (aes256cbc == NULL
|| ssl_hmac_init(hctx, tctx->ext.secure->tick_hmac_key,
sizeof(tctx->ext.secure->tick_hmac_key),
"SHA256") <= 0
|| EVP_DecryptInit_ex(ctx, aes256cbc, NULL,
tctx->ext.secure->tick_aes_key,
etick + TLSEXT_KEYNAME_LENGTH) <= 0) {
EVP_CIPHER_free(aes256cbc);
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
EVP_CIPHER_free(aes256cbc);
if (SSL_IS_TLS13(s))
renew_ticket = 1;
}
/*
* Attempt to process session ticket, first conduct sanity and integrity
* checks on ticket.
*/
mlen = ssl_hmac_size(hctx);
if (mlen == 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
if (ivlen < 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
/* Sanity check ticket length: must exceed keyname + IV + HMAC */
if (eticklen <= TLSEXT_KEYNAME_LENGTH + ivlen + mlen) {
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
eticklen -= mlen;
/* Check HMAC of encrypted ticket */
if (ssl_hmac_update(hctx, etick, eticklen) <= 0
|| ssl_hmac_final(hctx, tick_hmac, NULL, sizeof(tick_hmac)) <= 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) {
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
/* Attempt to decrypt session data */
/* Move p after IV to start of encrypted ticket, update length */
p = etick + TLSEXT_KEYNAME_LENGTH + ivlen;
eticklen -= TLSEXT_KEYNAME_LENGTH + ivlen;
sdec = OPENSSL_malloc(eticklen);
if (sdec == NULL || EVP_DecryptUpdate(ctx, sdec, &slen, p,
(int)eticklen) <= 0) {
OPENSSL_free(sdec);
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
if (EVP_DecryptFinal(ctx, sdec + slen, &declen) <= 0) {
OPENSSL_free(sdec);
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
slen += declen;
p = sdec;
sess = d2i_SSL_SESSION(NULL, &p, slen);
slen -= p - sdec;
OPENSSL_free(sdec);
if (sess) {
/* Some additional consistency checks */
if (slen != 0) {
SSL_SESSION_free(sess);
sess = NULL;
ret = SSL_TICKET_NO_DECRYPT;
goto end;
}
/*
* The session ID, if non-empty, is used by some clients to detect
* that the ticket has been accepted. So we copy it to the session
* structure. If it is empty set length to zero as required by
* standard.
*/
if (sesslen) {
memcpy(sess->session_id, sess_id, sesslen);
sess->session_id_length = sesslen;
}
if (renew_ticket)
ret = SSL_TICKET_SUCCESS_RENEW;
else
ret = SSL_TICKET_SUCCESS;
goto end;
}
ERR_clear_error();
/*
* For session parse failure, indicate that we need to send a new ticket.
*/
ret = SSL_TICKET_NO_DECRYPT;
end:
EVP_CIPHER_CTX_free(ctx);
ssl_hmac_free(hctx);
/*
* If set, the decrypt_ticket_cb() is called unless a fatal error was
* detected above. The callback is responsible for checking |ret| before it
* performs any action
*/
if (s->session_ctx->decrypt_ticket_cb != NULL
&& (ret == SSL_TICKET_EMPTY
|| ret == SSL_TICKET_NO_DECRYPT
|| ret == SSL_TICKET_SUCCESS
|| ret == SSL_TICKET_SUCCESS_RENEW)) {
size_t keyname_len = eticklen;
int retcb;
if (keyname_len > TLSEXT_KEYNAME_LENGTH)
keyname_len = TLSEXT_KEYNAME_LENGTH;
retcb = s->session_ctx->decrypt_ticket_cb(s, sess, etick, keyname_len,
ret,
s->session_ctx->ticket_cb_data);
switch (retcb) {
case SSL_TICKET_RETURN_ABORT:
ret = SSL_TICKET_FATAL_ERR_OTHER;
break;
case SSL_TICKET_RETURN_IGNORE:
ret = SSL_TICKET_NONE;
SSL_SESSION_free(sess);
sess = NULL;
break;
case SSL_TICKET_RETURN_IGNORE_RENEW:
if (ret != SSL_TICKET_EMPTY && ret != SSL_TICKET_NO_DECRYPT)
ret = SSL_TICKET_NO_DECRYPT;
/* else the value of |ret| will already do the right thing */
SSL_SESSION_free(sess);
sess = NULL;
break;
case SSL_TICKET_RETURN_USE:
case SSL_TICKET_RETURN_USE_RENEW:
if (ret != SSL_TICKET_SUCCESS
&& ret != SSL_TICKET_SUCCESS_RENEW)
ret = SSL_TICKET_FATAL_ERR_OTHER;
else if (retcb == SSL_TICKET_RETURN_USE)
ret = SSL_TICKET_SUCCESS;
else
ret = SSL_TICKET_SUCCESS_RENEW;
break;
default:
ret = SSL_TICKET_FATAL_ERR_OTHER;
}
}
if (s->ext.session_secret_cb == NULL || SSL_IS_TLS13(s)) {
switch (ret) {
case SSL_TICKET_NO_DECRYPT:
case SSL_TICKET_SUCCESS_RENEW:
case SSL_TICKET_EMPTY:
s->ext.ticket_expected = 1;
}
}
*psess = sess;
return ret;
}
/* Check to see if a signature algorithm is allowed */
static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
{
unsigned char sigalgstr[2];
int secbits;
if (lu == NULL || !lu->enabled)
return 0;
/* DSA is not allowed in TLS 1.3 */
if (SSL_IS_TLS13(s) && lu->sig == EVP_PKEY_DSA)
return 0;
/*
* At some point we should fully axe DSA/etc. in ClientHello as per TLS 1.3
* spec
*/
if (!s->server && !SSL_IS_DTLS(s) && s->s3.tmp.min_ver >= TLS1_3_VERSION
&& (lu->sig == EVP_PKEY_DSA || lu->hash_idx == SSL_MD_SHA1_IDX
|| lu->hash_idx == SSL_MD_MD5_IDX
|| lu->hash_idx == SSL_MD_SHA224_IDX))
return 0;
/* See if public key algorithm allowed */
if (ssl_cert_is_disabled(s->ctx, lu->sig_idx))
return 0;
if (lu->sig == NID_id_GostR3410_2012_256
|| lu->sig == NID_id_GostR3410_2012_512
|| lu->sig == NID_id_GostR3410_2001) {
/* We never allow GOST sig algs on the server with TLSv1.3 */
if (s->server && SSL_IS_TLS13(s))
return 0;
if (!s->server
&& s->method->version == TLS_ANY_VERSION
&& s->s3.tmp.max_ver >= TLS1_3_VERSION) {
int i, num;
STACK_OF(SSL_CIPHER) *sk;
/*
* We're a client that could negotiate TLSv1.3. We only allow GOST
* sig algs if we could negotiate TLSv1.2 or below and we have GOST
* ciphersuites enabled.
*/
if (s->s3.tmp.min_ver >= TLS1_3_VERSION)
return 0;
sk = SSL_get_ciphers(s);
num = sk != NULL ? sk_SSL_CIPHER_num(sk) : 0;
for (i = 0; i < num; i++) {
const SSL_CIPHER *c;
c = sk_SSL_CIPHER_value(sk, i);
/* Skip disabled ciphers */
if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0))
continue;
if ((c->algorithm_mkey & (SSL_kGOST | SSL_kGOST18)) != 0)
break;
}
if (i == num)
return 0;
}
}
/* Finally see if security callback allows it */
secbits = sigalg_security_bits(s->ctx, lu);
sigalgstr[0] = (lu->sigalg >> 8) & 0xff;
sigalgstr[1] = lu->sigalg & 0xff;
return ssl_security(s, op, secbits, lu->hash, (void *)sigalgstr);
}
/*
* Get a mask of disabled public key algorithms based on supported signature
* algorithms. For example if no signature algorithm supports RSA then RSA is
* disabled.
*/
void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op)
{
const uint16_t *sigalgs;
size_t i, sigalgslen;
uint32_t disabled_mask = SSL_aRSA | SSL_aDSS | SSL_aECDSA;
/*
* Go through all signature algorithms seeing if we support any
* in disabled_mask.
*/
sigalgslen = tls12_get_psigalgs(s, 1, &sigalgs);
for (i = 0; i < sigalgslen; i++, sigalgs++) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *sigalgs);
const SSL_CERT_LOOKUP *clu;
if (lu == NULL)
continue;
clu = ssl_cert_lookup_by_idx(lu->sig_idx);
if (clu == NULL)
continue;
/* If algorithm is disabled see if we can enable it */
if ((clu->amask & disabled_mask) != 0
&& tls12_sigalg_allowed(s, op, lu))
disabled_mask &= ~clu->amask;
}
*pmask_a |= disabled_mask;
}
int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
const uint16_t *psig, size_t psiglen)
{
size_t i;
int rv = 0;
for (i = 0; i < psiglen; i++, psig++) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *psig);
if (lu == NULL
|| !tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
continue;
if (!WPACKET_put_bytes_u16(pkt, *psig))
return 0;
/*
* If TLS 1.3 must have at least one valid TLS 1.3 message
* signing algorithm: i.e. neither RSA nor SHA1/SHA224
*/
if (rv == 0 && (!SSL_IS_TLS13(s)
|| (lu->sig != EVP_PKEY_RSA
&& lu->hash != NID_sha1
&& lu->hash != NID_sha224)))
rv = 1;
}
if (rv == 0)
ERR_raise(ERR_LIB_SSL, SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return rv;
}
/* Given preference and allowed sigalgs set shared sigalgs */
static size_t tls12_shared_sigalgs(SSL *s, const SIGALG_LOOKUP **shsig,
const uint16_t *pref, size_t preflen,
const uint16_t *allow, size_t allowlen)
{
const uint16_t *ptmp, *atmp;
size_t i, j, nmatch = 0;
for (i = 0, ptmp = pref; i < preflen; i++, ptmp++) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *ptmp);
/* Skip disabled hashes or signature algorithms */
if (lu == NULL
|| !tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, lu))
continue;
for (j = 0, atmp = allow; j < allowlen; j++, atmp++) {
if (*ptmp == *atmp) {
nmatch++;
if (shsig)
*shsig++ = lu;
break;
}
}
}
return nmatch;
}
/* Set shared signature algorithms for SSL structures */
static int tls1_set_shared_sigalgs(SSL *s)
{
const uint16_t *pref, *allow, *conf;
size_t preflen, allowlen, conflen;
size_t nmatch;
const SIGALG_LOOKUP **salgs = NULL;
CERT *c = s->cert;
unsigned int is_suiteb = tls1_suiteb(s);
OPENSSL_free(s->shared_sigalgs);
s->shared_sigalgs = NULL;
s->shared_sigalgslen = 0;
/* If client use client signature algorithms if not NULL */
if (!s->server && c->client_sigalgs && !is_suiteb) {
conf = c->client_sigalgs;
conflen = c->client_sigalgslen;
} else if (c->conf_sigalgs && !is_suiteb) {
conf = c->conf_sigalgs;
conflen = c->conf_sigalgslen;
} else
conflen = tls12_get_psigalgs(s, 0, &conf);
if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || is_suiteb) {
pref = conf;
preflen = conflen;
allow = s->s3.tmp.peer_sigalgs;
allowlen = s->s3.tmp.peer_sigalgslen;
} else {
allow = conf;
allowlen = conflen;
pref = s->s3.tmp.peer_sigalgs;
preflen = s->s3.tmp.peer_sigalgslen;
}
nmatch = tls12_shared_sigalgs(s, NULL, pref, preflen, allow, allowlen);
if (nmatch) {
if ((salgs = OPENSSL_malloc(nmatch * sizeof(*salgs))) == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
nmatch = tls12_shared_sigalgs(s, salgs, pref, preflen, allow, allowlen);
} else {
salgs = NULL;
}
s->shared_sigalgs = salgs;
s->shared_sigalgslen = nmatch;
return 1;
}
int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen)
{
unsigned int stmp;
size_t size, i;
uint16_t *buf;
size = PACKET_remaining(pkt);
/* Invalid data length */
if (size == 0 || (size & 1) != 0)
return 0;
size >>= 1;
if ((buf = OPENSSL_malloc(size * sizeof(*buf))) == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0; i < size && PACKET_get_net_2(pkt, &stmp); i++)
buf[i] = stmp;
if (i != size) {
OPENSSL_free(buf);
return 0;
}
OPENSSL_free(*pdest);
*pdest = buf;
*pdestlen = size;
return 1;
}
int tls1_save_sigalgs(SSL *s, PACKET *pkt, int cert)
{
/* Extension ignored for inappropriate versions */
if (!SSL_USE_SIGALGS(s))
return 1;
/* Should never happen */
if (s->cert == NULL)
return 0;
if (cert)
return tls1_save_u16(pkt, &s->s3.tmp.peer_cert_sigalgs,
&s->s3.tmp.peer_cert_sigalgslen);
else
return tls1_save_u16(pkt, &s->s3.tmp.peer_sigalgs,
&s->s3.tmp.peer_sigalgslen);
}
/* Set preferred digest for each key type */
int tls1_process_sigalgs(SSL *s)
{
size_t i;
uint32_t *pvalid = s->s3.tmp.valid_flags;
if (!tls1_set_shared_sigalgs(s))
return 0;
for (i = 0; i < SSL_PKEY_NUM; i++)
pvalid[i] = 0;
for (i = 0; i < s->shared_sigalgslen; i++) {
const SIGALG_LOOKUP *sigptr = s->shared_sigalgs[i];
int idx = sigptr->sig_idx;
/* Ignore PKCS1 based sig algs in TLSv1.3 */
if (SSL_IS_TLS13(s) && sigptr->sig == EVP_PKEY_RSA)
continue;
/* If not disabled indicate we can explicitly sign */
if (pvalid[idx] == 0 && !ssl_cert_is_disabled(s->ctx, idx))
pvalid[idx] = CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
}
return 1;
}
int SSL_get_sigalgs(SSL *s, int idx,
int *psign, int *phash, int *psignhash,
unsigned char *rsig, unsigned char *rhash)
{
uint16_t *psig = s->s3.tmp.peer_sigalgs;
size_t numsigalgs = s->s3.tmp.peer_sigalgslen;
if (psig == NULL || numsigalgs > INT_MAX)
return 0;
if (idx >= 0) {
const SIGALG_LOOKUP *lu;
if (idx >= (int)numsigalgs)
return 0;
psig += idx;
if (rhash != NULL)
*rhash = (unsigned char)((*psig >> 8) & 0xff);
if (rsig != NULL)
*rsig = (unsigned char)(*psig & 0xff);
lu = tls1_lookup_sigalg(s, *psig);
if (psign != NULL)
*psign = lu != NULL ? lu->sig : NID_undef;
if (phash != NULL)
*phash = lu != NULL ? lu->hash : NID_undef;
if (psignhash != NULL)
*psignhash = lu != NULL ? lu->sigandhash : NID_undef;
}
return (int)numsigalgs;
}
int SSL_get_shared_sigalgs(SSL *s, int idx,
int *psign, int *phash, int *psignhash,
unsigned char *rsig, unsigned char *rhash)
{
const SIGALG_LOOKUP *shsigalgs;
if (s->shared_sigalgs == NULL
|| idx < 0
|| idx >= (int)s->shared_sigalgslen
|| s->shared_sigalgslen > INT_MAX)
return 0;
shsigalgs = s->shared_sigalgs[idx];
if (phash != NULL)
*phash = shsigalgs->hash;
if (psign != NULL)
*psign = shsigalgs->sig;
if (psignhash != NULL)
*psignhash = shsigalgs->sigandhash;
if (rsig != NULL)
*rsig = (unsigned char)(shsigalgs->sigalg & 0xff);
if (rhash != NULL)
*rhash = (unsigned char)((shsigalgs->sigalg >> 8) & 0xff);
return (int)s->shared_sigalgslen;
}
/* Maximum possible number of unique entries in sigalgs array */
#define TLS_MAX_SIGALGCNT (OSSL_NELEM(sigalg_lookup_tbl) * 2)
typedef struct {
size_t sigalgcnt;
/* TLSEXT_SIGALG_XXX values */
uint16_t sigalgs[TLS_MAX_SIGALGCNT];
} sig_cb_st;
static void get_sigorhash(int *psig, int *phash, const char *str)
{
if (strcmp(str, "RSA") == 0) {
*psig = EVP_PKEY_RSA;
} else if (strcmp(str, "RSA-PSS") == 0 || strcmp(str, "PSS") == 0) {
*psig = EVP_PKEY_RSA_PSS;
} else if (strcmp(str, "DSA") == 0) {
*psig = EVP_PKEY_DSA;
} else if (strcmp(str, "ECDSA") == 0) {
*psig = EVP_PKEY_EC;
} else {
*phash = OBJ_sn2nid(str);
if (*phash == NID_undef)
*phash = OBJ_ln2nid(str);
}
}
/* Maximum length of a signature algorithm string component */
#define TLS_MAX_SIGSTRING_LEN 40
static int sig_cb(const char *elem, int len, void *arg)
{
sig_cb_st *sarg = arg;
size_t i;
const SIGALG_LOOKUP *s;
char etmp[TLS_MAX_SIGSTRING_LEN], *p;
int sig_alg = NID_undef, hash_alg = NID_undef;
if (elem == NULL)
return 0;
if (sarg->sigalgcnt == TLS_MAX_SIGALGCNT)
return 0;
if (len > (int)(sizeof(etmp) - 1))
return 0;
memcpy(etmp, elem, len);
etmp[len] = 0;
p = strchr(etmp, '+');
/*
* We only allow SignatureSchemes listed in the sigalg_lookup_tbl;
* if there's no '+' in the provided name, look for the new-style combined
* name. If not, match both sig+hash to find the needed SIGALG_LOOKUP.
* Just sig+hash is not unique since TLS 1.3 adds rsa_pss_pss_* and
* rsa_pss_rsae_* that differ only by public key OID; in such cases
* we will pick the _rsae_ variant, by virtue of them appearing earlier
* in the table.
*/
if (p == NULL) {
for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
i++, s++) {
if (s->name != NULL && strcmp(etmp, s->name) == 0) {
sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg;
break;
}
}
if (i == OSSL_NELEM(sigalg_lookup_tbl))
return 0;
} else {
*p = 0;
p++;
if (*p == 0)
return 0;
get_sigorhash(&sig_alg, &hash_alg, etmp);
get_sigorhash(&sig_alg, &hash_alg, p);
if (sig_alg == NID_undef || hash_alg == NID_undef)
return 0;
for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
i++, s++) {
if (s->hash == hash_alg && s->sig == sig_alg) {
sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg;
break;
}
}
if (i == OSSL_NELEM(sigalg_lookup_tbl))
return 0;
}
/* Reject duplicates */
for (i = 0; i < sarg->sigalgcnt - 1; i++) {
if (sarg->sigalgs[i] == sarg->sigalgs[sarg->sigalgcnt - 1]) {
sarg->sigalgcnt--;
return 0;
}
}
return 1;
}
/*
* Set supported signature algorithms based on a colon separated list of the
* form sig+hash e.g. RSA+SHA512:DSA+SHA512
*/
int tls1_set_sigalgs_list(CERT *c, const char *str, int client)
{
sig_cb_st sig;
sig.sigalgcnt = 0;
if (!CONF_parse_list(str, ':', 1, sig_cb, &sig))
return 0;
if (c == NULL)
return 1;
return tls1_set_raw_sigalgs(c, sig.sigalgs, sig.sigalgcnt, client);
}
int tls1_set_raw_sigalgs(CERT *c, const uint16_t *psigs, size_t salglen,
int client)
{
uint16_t *sigalgs;
if ((sigalgs = OPENSSL_malloc(salglen * sizeof(*sigalgs))) == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(sigalgs, psigs, salglen * sizeof(*sigalgs));
if (client) {
OPENSSL_free(c->client_sigalgs);
c->client_sigalgs = sigalgs;
c->client_sigalgslen = salglen;
} else {
OPENSSL_free(c->conf_sigalgs);
c->conf_sigalgs = sigalgs;
c->conf_sigalgslen = salglen;
}
return 1;
}
int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen, int client)
{
uint16_t *sigalgs, *sptr;
size_t i;
if (salglen & 1)
return 0;
if ((sigalgs = OPENSSL_malloc((salglen / 2) * sizeof(*sigalgs))) == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0, sptr = sigalgs; i < salglen; i += 2) {
size_t j;
const SIGALG_LOOKUP *curr;
int md_id = *psig_nids++;
int sig_id = *psig_nids++;
for (j = 0, curr = sigalg_lookup_tbl; j < OSSL_NELEM(sigalg_lookup_tbl);
j++, curr++) {
if (curr->hash == md_id && curr->sig == sig_id) {
*sptr++ = curr->sigalg;
break;
}
}
if (j == OSSL_NELEM(sigalg_lookup_tbl))
goto err;
}
if (client) {
OPENSSL_free(c->client_sigalgs);
c->client_sigalgs = sigalgs;
c->client_sigalgslen = salglen / 2;
} else {
OPENSSL_free(c->conf_sigalgs);
c->conf_sigalgs = sigalgs;
c->conf_sigalgslen = salglen / 2;
}
return 1;
err:
OPENSSL_free(sigalgs);
return 0;
}
static int tls1_check_sig_alg(SSL *s, X509 *x, int default_nid)
{
int sig_nid, use_pc_sigalgs = 0;
size_t i;
const SIGALG_LOOKUP *sigalg;
size_t sigalgslen;
if (default_nid == -1)
return 1;
sig_nid = X509_get_signature_nid(x);
if (default_nid)
return sig_nid == default_nid ? 1 : 0;
if (SSL_IS_TLS13(s) && s->s3.tmp.peer_cert_sigalgs != NULL) {
/*
* If we're in TLSv1.3 then we only get here if we're checking the
* chain. If the peer has specified peer_cert_sigalgs then we use them
* otherwise we default to normal sigalgs.
*/
sigalgslen = s->s3.tmp.peer_cert_sigalgslen;
use_pc_sigalgs = 1;
} else {
sigalgslen = s->shared_sigalgslen;
}
for (i = 0; i < sigalgslen; i++) {
sigalg = use_pc_sigalgs
? tls1_lookup_sigalg(s, s->s3.tmp.peer_cert_sigalgs[i])
: s->shared_sigalgs[i];
if (sigalg != NULL && sig_nid == sigalg->sigandhash)
return 1;
}
return 0;
}
/* Check to see if a certificate issuer name matches list of CA names */
static int ssl_check_ca_name(STACK_OF(X509_NAME) *names, X509 *x)
{
const X509_NAME *nm;
int i;
nm = X509_get_issuer_name(x);
for (i = 0; i < sk_X509_NAME_num(names); i++) {
if (!X509_NAME_cmp(nm, sk_X509_NAME_value(names, i)))
return 1;
}
return 0;
}
/*
* Check certificate chain is consistent with TLS extensions and is usable by
* server. This servers two purposes: it allows users to check chains before
* passing them to the server and it allows the server to check chains before
* attempting to use them.
*/
/* Flags which need to be set for a certificate when strict mode not set */
#define CERT_PKEY_VALID_FLAGS \
(CERT_PKEY_EE_SIGNATURE|CERT_PKEY_EE_PARAM)
/* Strict mode flags */
#define CERT_PKEY_STRICT_FLAGS \
(CERT_PKEY_VALID_FLAGS|CERT_PKEY_CA_SIGNATURE|CERT_PKEY_CA_PARAM \
| CERT_PKEY_ISSUER_NAME|CERT_PKEY_CERT_TYPE)
int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
int idx)
{
int i;
int rv = 0;
int check_flags = 0, strict_mode;
CERT_PKEY *cpk = NULL;
CERT *c = s->cert;
uint32_t *pvalid;
unsigned int suiteb_flags = tls1_suiteb(s);
/* idx == -1 means checking server chains */
if (idx != -1) {
/* idx == -2 means checking client certificate chains */
if (idx == -2) {
cpk = c->key;
idx = (int)(cpk - c->pkeys);
} else
cpk = c->pkeys + idx;
pvalid = s->s3.tmp.valid_flags + idx;
x = cpk->x509;
pk = cpk->privatekey;
chain = cpk->chain;
strict_mode = c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT;
/* If no cert or key, forget it */
if (!x || !pk)
goto end;
} else {
size_t certidx;
if (!x || !pk)
return 0;
if (ssl_cert_lookup_by_pkey(pk, &certidx) == NULL)
return 0;
idx = certidx;
pvalid = s->s3.tmp.valid_flags + idx;
if (c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
check_flags = CERT_PKEY_STRICT_FLAGS;
else
check_flags = CERT_PKEY_VALID_FLAGS;
strict_mode = 1;
}
if (suiteb_flags) {
int ok;
if (check_flags)
check_flags |= CERT_PKEY_SUITEB;
ok = X509_chain_check_suiteb(NULL, x, chain, suiteb_flags);
if (ok == X509_V_OK)
rv |= CERT_PKEY_SUITEB;
else if (!check_flags)
goto end;
}
/*
* Check all signature algorithms are consistent with signature
* algorithms extension if TLS 1.2 or later and strict mode.
*/
if (TLS1_get_version(s) >= TLS1_2_VERSION && strict_mode) {
int default_nid;
int rsign = 0;
if (s->s3.tmp.peer_cert_sigalgs != NULL
|| s->s3.tmp.peer_sigalgs != NULL) {
default_nid = 0;
/* If no sigalgs extension use defaults from RFC5246 */
} else {
switch (idx) {
case SSL_PKEY_RSA:
rsign = EVP_PKEY_RSA;
default_nid = NID_sha1WithRSAEncryption;
break;
case SSL_PKEY_DSA_SIGN:
rsign = EVP_PKEY_DSA;
default_nid = NID_dsaWithSHA1;
break;
case SSL_PKEY_ECC:
rsign = EVP_PKEY_EC;
default_nid = NID_ecdsa_with_SHA1;
break;
case SSL_PKEY_GOST01:
rsign = NID_id_GostR3410_2001;
default_nid = NID_id_GostR3411_94_with_GostR3410_2001;
break;
case SSL_PKEY_GOST12_256:
rsign = NID_id_GostR3410_2012_256;
default_nid = NID_id_tc26_signwithdigest_gost3410_2012_256;
break;
case SSL_PKEY_GOST12_512:
rsign = NID_id_GostR3410_2012_512;
default_nid = NID_id_tc26_signwithdigest_gost3410_2012_512;
break;
default:
default_nid = -1;
break;
}
}
/*
* If peer sent no signature algorithms extension and we have set
* preferred signature algorithms check we support sha1.
*/
if (default_nid > 0 && c->conf_sigalgs) {
size_t j;
const uint16_t *p = c->conf_sigalgs;
for (j = 0; j < c->conf_sigalgslen; j++, p++) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *p);
if (lu != NULL && lu->hash == NID_sha1 && lu->sig == rsign)
break;
}
if (j == c->conf_sigalgslen) {
if (check_flags)
goto skip_sigs;
else
goto end;
}
}
/* Check signature algorithm of each cert in chain */
if (SSL_IS_TLS13(s)) {
/*
* We only get here if the application has called SSL_check_chain(),
* so check_flags is always set.
*/
if (find_sig_alg(s, x, pk) != NULL)
rv |= CERT_PKEY_EE_SIGNATURE;
} else if (!tls1_check_sig_alg(s, x, default_nid)) {
if (!check_flags)
goto end;
} else
rv |= CERT_PKEY_EE_SIGNATURE;
rv |= CERT_PKEY_CA_SIGNATURE;
for (i = 0; i < sk_X509_num(chain); i++) {
if (!tls1_check_sig_alg(s, sk_X509_value(chain, i), default_nid)) {
if (check_flags) {
rv &= ~CERT_PKEY_CA_SIGNATURE;
break;
} else
goto end;
}
}
}
/* Else not TLS 1.2, so mark EE and CA signing algorithms OK */
else if (check_flags)
rv |= CERT_PKEY_EE_SIGNATURE | CERT_PKEY_CA_SIGNATURE;
skip_sigs:
/* Check cert parameters are consistent */
if (tls1_check_cert_param(s, x, 1))
rv |= CERT_PKEY_EE_PARAM;
else if (!check_flags)
goto end;
if (!s->server)
rv |= CERT_PKEY_CA_PARAM;
/* In strict mode check rest of chain too */
else if (strict_mode) {
rv |= CERT_PKEY_CA_PARAM;
for (i = 0; i < sk_X509_num(chain); i++) {
X509 *ca = sk_X509_value(chain, i);
if (!tls1_check_cert_param(s, ca, 0)) {
if (check_flags) {
rv &= ~CERT_PKEY_CA_PARAM;
break;
} else
goto end;
}
}
}
if (!s->server && strict_mode) {
STACK_OF(X509_NAME) *ca_dn;
int check_type = 0;
if (EVP_PKEY_is_a(pk, "RSA"))
check_type = TLS_CT_RSA_SIGN;
else if (EVP_PKEY_is_a(pk, "DSA"))
check_type = TLS_CT_DSS_SIGN;
else if (EVP_PKEY_is_a(pk, "EC"))
check_type = TLS_CT_ECDSA_SIGN;
if (check_type) {
const uint8_t *ctypes = s->s3.tmp.ctype;
size_t j;
for (j = 0; j < s->s3.tmp.ctype_len; j++, ctypes++) {
if (*ctypes == check_type) {
rv |= CERT_PKEY_CERT_TYPE;
break;
}
}
if (!(rv & CERT_PKEY_CERT_TYPE) && !check_flags)
goto end;
} else {
rv |= CERT_PKEY_CERT_TYPE;
}
ca_dn = s->s3.tmp.peer_ca_names;
if (ca_dn == NULL
|| sk_X509_NAME_num(ca_dn) == 0
|| ssl_check_ca_name(ca_dn, x))
rv |= CERT_PKEY_ISSUER_NAME;
else
for (i = 0; i < sk_X509_num(chain); i++) {
X509 *xtmp = sk_X509_value(chain, i);
if (ssl_check_ca_name(ca_dn, xtmp)) {
rv |= CERT_PKEY_ISSUER_NAME;
break;
}
}
if (!check_flags && !(rv & CERT_PKEY_ISSUER_NAME))
goto end;
} else
rv |= CERT_PKEY_ISSUER_NAME | CERT_PKEY_CERT_TYPE;
if (!check_flags || (rv & check_flags) == check_flags)
rv |= CERT_PKEY_VALID;
end:
if (TLS1_get_version(s) >= TLS1_2_VERSION)
rv |= *pvalid & (CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN);
else
rv |= CERT_PKEY_SIGN | CERT_PKEY_EXPLICIT_SIGN;
/*
* When checking a CERT_PKEY structure all flags are irrelevant if the
* chain is invalid.
*/
if (!check_flags) {
if (rv & CERT_PKEY_VALID) {
*pvalid = rv;
} else {
/* Preserve sign and explicit sign flag, clear rest */
*pvalid &= CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
return 0;
}
}
return rv;
}
/* Set validity of certificates in an SSL structure */
void tls1_set_cert_validity(SSL *s)
{
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_PSS_SIGN);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DSA_SIGN);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ECC);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST01);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_256);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_512);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ED25519);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ED448);
}
/* User level utility function to check a chain is suitable */
int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
{
return tls1_check_chain(s, x, pk, chain, -1);
}
EVP_PKEY *ssl_get_auto_dh(SSL *s)
{
EVP_PKEY *dhp = NULL;
BIGNUM *p;
int dh_secbits = 80, sec_level_bits;
EVP_PKEY_CTX *pctx = NULL;
OSSL_PARAM_BLD *tmpl = NULL;
OSSL_PARAM *params = NULL;
if (s->cert->dh_tmp_auto != 2) {
if (s->s3.tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aPSK)) {
if (s->s3.tmp.new_cipher->strength_bits == 256)
dh_secbits = 128;
else
dh_secbits = 80;
} else {
if (s->s3.tmp.cert == NULL)
return NULL;
dh_secbits = EVP_PKEY_get_security_bits(s->s3.tmp.cert->privatekey);
}
}
/* Do not pick a prime that is too weak for the current security level */
sec_level_bits = ssl_get_security_level_bits(s, NULL, NULL);
if (dh_secbits < sec_level_bits)
dh_secbits = sec_level_bits;
if (dh_secbits >= 192)
p = BN_get_rfc3526_prime_8192(NULL);
else if (dh_secbits >= 152)
p = BN_get_rfc3526_prime_4096(NULL);
else if (dh_secbits >= 128)
p = BN_get_rfc3526_prime_3072(NULL);
else if (dh_secbits >= 112)
p = BN_get_rfc3526_prime_2048(NULL);
else
p = BN_get_rfc2409_prime_1024(NULL);
if (p == NULL)
goto err;
pctx = EVP_PKEY_CTX_new_from_name(s->ctx->libctx, "DH", s->ctx->propq);
if (pctx == NULL
|| EVP_PKEY_fromdata_init(pctx) != 1)
goto err;
tmpl = OSSL_PARAM_BLD_new();
if (tmpl == NULL
|| !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p)
|| !OSSL_PARAM_BLD_push_uint(tmpl, OSSL_PKEY_PARAM_FFC_G, 2))
goto err;
params = OSSL_PARAM_BLD_to_param(tmpl);
if (params == NULL
|| EVP_PKEY_fromdata(pctx, &dhp, EVP_PKEY_KEY_PARAMETERS, params) != 1)
goto err;
err:
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(tmpl);
EVP_PKEY_CTX_free(pctx);
BN_free(p);
return dhp;
}
static int ssl_security_cert_key(SSL *s, SSL_CTX *ctx, X509 *x, int op)
{
int secbits = -1;
EVP_PKEY *pkey = X509_get0_pubkey(x);
if (pkey) {
/*
* If no parameters this will return -1 and fail using the default
* security callback for any non-zero security level. This will
* reject keys which omit parameters but this only affects DSA and
* omission of parameters is never (?) done in practice.
*/
secbits = EVP_PKEY_get_security_bits(pkey);
}
if (s)
return ssl_security(s, op, secbits, 0, x);
else
return ssl_ctx_security(ctx, op, secbits, 0, x);
}
static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op)
{
/* Lookup signature algorithm digest */
int secbits, nid, pknid;
/* Don't check signature if self signed */
if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0)
return 1;
if (!X509_get_signature_info(x, &nid, &pknid, &secbits, NULL))
secbits = -1;
/* If digest NID not defined use signature NID */
if (nid == NID_undef)
nid = pknid;
if (s)
return ssl_security(s, op, secbits, nid, x);
else
return ssl_ctx_security(ctx, op, secbits, nid, x);
}
int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee)
{
if (vfy)
vfy = SSL_SECOP_PEER;
if (is_ee) {
if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_EE_KEY | vfy))
return SSL_R_EE_KEY_TOO_SMALL;
} else {
if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_CA_KEY | vfy))
return SSL_R_CA_KEY_TOO_SMALL;
}
if (!ssl_security_cert_sig(s, ctx, x, SSL_SECOP_CA_MD | vfy))
return SSL_R_CA_MD_TOO_WEAK;
return 1;
}
/*
* Check security of a chain, if |sk| includes the end entity certificate then
* |x| is NULL. If |vfy| is 1 then we are verifying a peer chain and not sending
* one to the peer. Return values: 1 if ok otherwise error code to use
*/
int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *x, int vfy)
{
int rv, start_idx, i;
if (x == NULL) {
x = sk_X509_value(sk, 0);
if (x == NULL)
return ERR_R_INTERNAL_ERROR;
start_idx = 1;
} else
start_idx = 0;
rv = ssl_security_cert(s, NULL, x, vfy, 1);
if (rv != 1)
return rv;
for (i = start_idx; i < sk_X509_num(sk); i++) {
x = sk_X509_value(sk, i);
rv = ssl_security_cert(s, NULL, x, vfy, 0);
if (rv != 1)
return rv;
}
return 1;
}
/*
* For TLS 1.2 servers check if we have a certificate which can be used
* with the signature algorithm "lu" and return index of certificate.
*/
static int tls12_get_cert_sigalg_idx(const SSL *s, const SIGALG_LOOKUP *lu)
{
int sig_idx = lu->sig_idx;
const SSL_CERT_LOOKUP *clu = ssl_cert_lookup_by_idx(sig_idx);
/* If not recognised or not supported by cipher mask it is not suitable */
if (clu == NULL
|| (clu->amask & s->s3.tmp.new_cipher->algorithm_auth) == 0
|| (clu->nid == EVP_PKEY_RSA_PSS
&& (s->s3.tmp.new_cipher->algorithm_mkey & SSL_kRSA) != 0))
return -1;
return s->s3.tmp.valid_flags[sig_idx] & CERT_PKEY_VALID ? sig_idx : -1;
}
/*
* Checks the given cert against signature_algorithm_cert restrictions sent by
* the peer (if any) as well as whether the hash from the sigalg is usable with
* the key.
* Returns true if the cert is usable and false otherwise.
*/
static int check_cert_usable(SSL *s, const SIGALG_LOOKUP *sig, X509 *x,
EVP_PKEY *pkey)
{
const SIGALG_LOOKUP *lu;
int mdnid, pknid, supported;
size_t i;
const char *mdname = NULL;
/*
* If the given EVP_PKEY cannot support signing with this digest,
* the answer is simply 'no'.
*/
if (sig->hash != NID_undef)
mdname = OBJ_nid2sn(sig->hash);
supported = EVP_PKEY_digestsign_supports_digest(pkey, s->ctx->libctx,
mdname,
s->ctx->propq);
if (supported <= 0)
return 0;
/*
* The TLS 1.3 signature_algorithms_cert extension places restrictions
* on the sigalg with which the certificate was signed (by its issuer).
*/
if (s->s3.tmp.peer_cert_sigalgs != NULL) {
if (!X509_get_signature_info(x, &mdnid, &pknid, NULL, NULL))
return 0;
for (i = 0; i < s->s3.tmp.peer_cert_sigalgslen; i++) {
lu = tls1_lookup_sigalg(s, s->s3.tmp.peer_cert_sigalgs[i]);
if (lu == NULL)
continue;
/*
* This does not differentiate between the
* rsa_pss_pss_* and rsa_pss_rsae_* schemes since we do not
* have a chain here that lets us look at the key OID in the
* signing certificate.
*/
if (mdnid == lu->hash && pknid == lu->sig)
return 1;
}
return 0;
}
/*
* Without signat_algorithms_cert, any certificate for which we have
* a viable public key is permitted.
*/
return 1;
}
/*
* Returns true if |s| has a usable certificate configured for use
* with signature scheme |sig|.
* "Usable" includes a check for presence as well as applying
* the signature_algorithm_cert restrictions sent by the peer (if any).
* Returns false if no usable certificate is found.
*/
static int has_usable_cert(SSL *s, const SIGALG_LOOKUP *sig, int idx)
{
/* TLS 1.2 callers can override sig->sig_idx, but not TLS 1.3 callers. */
if (idx == -1)
idx = sig->sig_idx;
if (!ssl_has_cert(s, idx))
return 0;
return check_cert_usable(s, sig, s->cert->pkeys[idx].x509,
s->cert->pkeys[idx].privatekey);
}
/*
* Returns true if the supplied cert |x| and key |pkey| is usable with the
* specified signature scheme |sig|, or false otherwise.
*/
static int is_cert_usable(SSL *s, const SIGALG_LOOKUP *sig, X509 *x,
EVP_PKEY *pkey)
{
size_t idx;
if (ssl_cert_lookup_by_pkey(pkey, &idx) == NULL)
return 0;
/* Check the key is consistent with the sig alg */
if ((int)idx != sig->sig_idx)
return 0;
return check_cert_usable(s, sig, x, pkey);
}
/*
* Find a signature scheme that works with the supplied certificate |x| and key
* |pkey|. |x| and |pkey| may be NULL in which case we additionally look at our
* available certs/keys to find one that works.
*/
static const SIGALG_LOOKUP *find_sig_alg(SSL *s, X509 *x, EVP_PKEY *pkey)
{
const SIGALG_LOOKUP *lu = NULL;
size_t i;
int curve = -1;
EVP_PKEY *tmppkey;
/* Look for a shared sigalgs matching possible certificates */
for (i = 0; i < s->shared_sigalgslen; i++) {
lu = s->shared_sigalgs[i];
/* Skip SHA1, SHA224, DSA and RSA if not PSS */
if (lu->hash == NID_sha1
|| lu->hash == NID_sha224
|| lu->sig == EVP_PKEY_DSA
|| lu->sig == EVP_PKEY_RSA)
continue;
/* Check that we have a cert, and signature_algorithms_cert */
if (!tls1_lookup_md(s->ctx, lu, NULL))
continue;
if ((pkey == NULL && !has_usable_cert(s, lu, -1))
|| (pkey != NULL && !is_cert_usable(s, lu, x, pkey)))
continue;
tmppkey = (pkey != NULL) ? pkey
: s->cert->pkeys[lu->sig_idx].privatekey;
if (lu->sig == EVP_PKEY_EC) {
if (curve == -1)
curve = ssl_get_EC_curve_nid(tmppkey);
if (lu->curve != NID_undef && curve != lu->curve)
continue;
} else if (lu->sig == EVP_PKEY_RSA_PSS) {
/* validate that key is large enough for the signature algorithm */
if (!rsa_pss_check_min_key_size(s->ctx, tmppkey, lu))
continue;
}
break;
}
if (i == s->shared_sigalgslen)
return NULL;
return lu;
}
/*
* Choose an appropriate signature algorithm based on available certificates
* Sets chosen certificate and signature algorithm.
*
* For servers if we fail to find a required certificate it is a fatal error,
* an appropriate error code is set and a TLS alert is sent.
*
* For clients fatalerrs is set to 0. If a certificate is not suitable it is not
* a fatal error: we will either try another certificate or not present one
* to the server. In this case no error is set.
*/
int tls_choose_sigalg(SSL *s, int fatalerrs)
{
const SIGALG_LOOKUP *lu = NULL;
int sig_idx = -1;
s->s3.tmp.cert = NULL;
s->s3.tmp.sigalg = NULL;
if (SSL_IS_TLS13(s)) {
lu = find_sig_alg(s, NULL, NULL);
if (lu == NULL) {
if (!fatalerrs)
return 1;
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
}
} else {
/* If ciphersuite doesn't require a cert nothing to do */
if (!(s->s3.tmp.new_cipher->algorithm_auth & SSL_aCERT))
return 1;
if (!s->server && !ssl_has_cert(s, s->cert->key - s->cert->pkeys))
return 1;
if (SSL_USE_SIGALGS(s)) {
size_t i;
if (s->s3.tmp.peer_sigalgs != NULL) {
int curve = -1;
/* For Suite B need to match signature algorithm to curve */
if (tls1_suiteb(s))
curve = ssl_get_EC_curve_nid(s->cert->pkeys[SSL_PKEY_ECC]
.privatekey);
/*
* Find highest preference signature algorithm matching
* cert type
*/
for (i = 0; i < s->shared_sigalgslen; i++) {
lu = s->shared_sigalgs[i];
if (s->server) {
if ((sig_idx = tls12_get_cert_sigalg_idx(s, lu)) == -1)
continue;
} else {
int cc_idx = s->cert->key - s->cert->pkeys;
sig_idx = lu->sig_idx;
if (cc_idx != sig_idx)
continue;
}
/* Check that we have a cert, and sig_algs_cert */
if (!has_usable_cert(s, lu, sig_idx))
continue;
if (lu->sig == EVP_PKEY_RSA_PSS) {
/* validate that key is large enough for the signature algorithm */
EVP_PKEY *pkey = s->cert->pkeys[sig_idx].privatekey;
if (!rsa_pss_check_min_key_size(s->ctx, pkey, lu))
continue;
}
if (curve == -1 || lu->curve == curve)
break;
}
#ifndef OPENSSL_NO_GOST
/*
* Some Windows-based implementations do not send GOST algorithms indication
* in supported_algorithms extension, so when we have GOST-based ciphersuite,
* we have to assume GOST support.
*/
if (i == s->shared_sigalgslen && s->s3.tmp.new_cipher->algorithm_auth & (SSL_aGOST01 | SSL_aGOST12)) {
if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
if (!fatalerrs)
return 1;
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
} else {
i = 0;
sig_idx = lu->sig_idx;
}
}
#endif
if (i == s->shared_sigalgslen) {
if (!fatalerrs)
return 1;
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
}
} else {
/*
* If we have no sigalg use defaults
*/
const uint16_t *sent_sigs;
size_t sent_sigslen;
if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
if (!fatalerrs)
return 1;
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
}
/* Check signature matches a type we sent */
sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
for (i = 0; i < sent_sigslen; i++, sent_sigs++) {
if (lu->sigalg == *sent_sigs
&& has_usable_cert(s, lu, lu->sig_idx))
break;
}
if (i == sent_sigslen) {
if (!fatalerrs)
return 1;
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
}
} else {
if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
if (!fatalerrs)
return 1;
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
}
}
}
if (sig_idx == -1)
sig_idx = lu->sig_idx;
s->s3.tmp.cert = &s->cert->pkeys[sig_idx];
s->cert->key = s->s3.tmp.cert;
s->s3.tmp.sigalg = lu;
return 1;
}
int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode)
{
if (mode != TLSEXT_max_fragment_length_DISABLED
&& !IS_MAX_FRAGMENT_LENGTH_EXT_VALID(mode)) {
ERR_raise(ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
ctx->ext.max_fragment_len_mode = mode;
return 1;
}
int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode)
{
if (mode != TLSEXT_max_fragment_length_DISABLED
&& !IS_MAX_FRAGMENT_LENGTH_EXT_VALID(mode)) {
ERR_raise(ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
ssl->ext.max_fragment_len_mode = mode;
return 1;
}
uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *session)
{
return session->ext.max_fragment_len_mode;
}
/*
* Helper functions for HMAC access with legacy support included.
*/
SSL_HMAC *ssl_hmac_new(const SSL_CTX *ctx)
{
SSL_HMAC *ret = OPENSSL_zalloc(sizeof(*ret));
EVP_MAC *mac = NULL;
if (ret == NULL)
return NULL;
#ifndef OPENSSL_NO_DEPRECATED_3_0
if (ctx->ext.ticket_key_evp_cb == NULL
&& ctx->ext.ticket_key_cb != NULL) {
if (!ssl_hmac_old_new(ret))
goto err;
return ret;
}
#endif
mac = EVP_MAC_fetch(ctx->libctx, "HMAC", ctx->propq);
if (mac == NULL || (ret->ctx = EVP_MAC_CTX_new(mac)) == NULL)
goto err;
EVP_MAC_free(mac);
return ret;
err:
EVP_MAC_CTX_free(ret->ctx);
EVP_MAC_free(mac);
OPENSSL_free(ret);
return NULL;
}
void ssl_hmac_free(SSL_HMAC *ctx)
{
if (ctx != NULL) {
EVP_MAC_CTX_free(ctx->ctx);
#ifndef OPENSSL_NO_DEPRECATED_3_0
ssl_hmac_old_free(ctx);
#endif
OPENSSL_free(ctx);
}
}
EVP_MAC_CTX *ssl_hmac_get0_EVP_MAC_CTX(SSL_HMAC *ctx)
{
return ctx->ctx;
}
int ssl_hmac_init(SSL_HMAC *ctx, void *key, size_t len, char *md)
{
OSSL_PARAM params[2], *p = params;
if (ctx->ctx != NULL) {
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, md, 0);
*p = OSSL_PARAM_construct_end();
if (EVP_MAC_init(ctx->ctx, key, len, params))
return 1;
}
#ifndef OPENSSL_NO_DEPRECATED_3_0
if (ctx->old_ctx != NULL)
return ssl_hmac_old_init(ctx, key, len, md);
#endif
return 0;
}
int ssl_hmac_update(SSL_HMAC *ctx, const unsigned char *data, size_t len)
{
if (ctx->ctx != NULL)
return EVP_MAC_update(ctx->ctx, data, len);
#ifndef OPENSSL_NO_DEPRECATED_3_0
if (ctx->old_ctx != NULL)
return ssl_hmac_old_update(ctx, data, len);
#endif
return 0;
}
int ssl_hmac_final(SSL_HMAC *ctx, unsigned char *md, size_t *len,
size_t max_size)
{
if (ctx->ctx != NULL)
return EVP_MAC_final(ctx->ctx, md, len, max_size);
#ifndef OPENSSL_NO_DEPRECATED_3_0
if (ctx->old_ctx != NULL)
return ssl_hmac_old_final(ctx, md, len);
#endif
return 0;
}
size_t ssl_hmac_size(const SSL_HMAC *ctx)
{
if (ctx->ctx != NULL)
return EVP_MAC_CTX_get_mac_size(ctx->ctx);
#ifndef OPENSSL_NO_DEPRECATED_3_0
if (ctx->old_ctx != NULL)
return ssl_hmac_old_size(ctx);
#endif
return 0;
}
int ssl_get_EC_curve_nid(const EVP_PKEY *pkey)
{
char gname[OSSL_MAX_NAME_SIZE];
if (EVP_PKEY_get_group_name(pkey, gname, sizeof(gname), NULL) > 0)
return OBJ_txt2nid(gname);
return NID_undef;
}
__owur int tls13_set_encoded_pub_key(EVP_PKEY *pkey,
const unsigned char *enckey,
size_t enckeylen)
{
if (EVP_PKEY_is_a(pkey, "DH")) {
int bits = EVP_PKEY_get_bits(pkey);
if (bits <= 0 || enckeylen != (size_t)bits / 8)
/* the encoded key must be padded to the length of the p */
return 0;
} else if (EVP_PKEY_is_a(pkey, "EC")) {
if (enckeylen < 3 /* point format and at least 1 byte for x and y */
|| enckey[0] != 0x04)
return 0;
}
return EVP_PKEY_set1_encoded_public_key(pkey, enckey, enckeylen);
}

File Metadata

Mime Type
application/octet-stream
Expires
Tue, Jul 2, 8:53 AM (2 d)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
5HX8BU8Gvnhh
Default Alt Text
(4 MB)

Event Timeline